From 6b618537128fbd33c5b6aff0f1a344802565e41b Mon Sep 17 00:00:00 2001 From: JustinOros Date: Thu, 24 Jul 2025 10:04:48 -0700 Subject: [PATCH] Monitor a website for changes. --- diff-web.py | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 diff-web.py diff --git a/diff-web.py b/diff-web.py new file mode 100644 index 0000000..22cdf07 --- /dev/null +++ b/diff-web.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# Description: Monitor a website for changes. +# Usage: python3 diff-web.py +# Author: Justin Oros +# Source: https://github.com/JustinOros + +import requests +import hashlib +import os +import time +import argparse +from urllib.parse import urlparse +from datetime import datetime + +def normalize_url(url): + if not urlparse(url).scheme: + url = 'https://' + url + return url + +def fetch_content(url): + response = requests.get(url, timeout=10) + response.raise_for_status() + return response.text + +def get_hash(content): + return hashlib.sha256(content.encode('utf-8')).hexdigest() + +def get_log_filename(url, override=None): + if override: + return override + domain = urlparse(url).netloc + return f"{domain}.log" + +def get_cache_filename(url): + domain = urlparse(url).netloc + return f".{domain}.cache" + +def log_message(message, log_file): + print(message) + with open(log_file, 'a') as f: + f.write(message + '\n') + +def monitor_website(url, interval, log_file_override=None): + url = normalize_url(url) + domain = urlparse(url).netloc + log_file = get_log_filename(url, log_file_override) + cache_file = get_cache_filename(url) + + log_message(f"[{datetime.now()}] Monitoring {domain}", log_file) + + while True: + try: + current_content = fetch_content(url) + current_hash = get_hash(current_content) + except Exception as e: + log_message(f"[{datetime.now()}] [ERROR] Failed to fetch {url}: {e}", log_file) + time.sleep(interval) + continue + + if os.path.exists(cache_file): + with open(cache_file, 'r') as f: + old_hash = f.read().strip() + if current_hash != old_hash: + msg = f"[{datetime.now()}] Change detected on {url}" + log_message(msg, log_file) + with open(cache_file, 'w') as f: + f.write(current_hash) + else: + msg = f"[{datetime.now()}] First-time check for {url}: storing baseline." + log_message(msg, log_file) + with open(cache_file, 'w') as f: + f.write(current_hash) + + time.sleep(interval) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Monitor a website for changes.") + parser.add_argument("url", help="The website URL or domain to monitor.") + parser.add_argument("-t", "--time", type=int, default=60, + help="Time interval between checks in seconds (default: 60).") + parser.add_argument("-l", "--log", type=str, + help="Optional log file name (default: domain.tld.log)") + + args = parser.parse_args() + monitor_website(args.url, args.time, args.log) +