Realizzare un Monitor Web in Python con Requests e BeautifulSoup

  

Ti è mai capitato di aggiornare ossessivamente una pagina web in attesa che un prodotto torni disponibile, o che vengano pubblicati gli esiti di un esame?

Oppure hai mai dovuto monitorare un sito per essere sicuro che fosse up&running (per intervenire tempestivamente in caso di problemi)?

Fare refresh manuale ogni giorno (o ogni ora!) è una perdita di tempo. Oggi vedremo come costruire un Monitor di Contenuti Web in Python: uno script leggero che controlla periodicamente uno specifico tag HTML su un sito e ti avvisa non appena rileva un cambiamento.

🔗 Ti piace Techelopment? Dai un'occhiata al sito per tutti i dettagli!

🛠️ Gli strumenti del mestiere

Per questo progetto usiamo due delle librerie più famose e amate dell'ecosistema Python:

  1. requests: La libreria standard de facto per effettuare richieste HTTP. Ci servirà per scaricare il codice HTML della pagina web target.
  2. beautifulsoup4 (BS4): Un fantastico parser HTML/XML che ci permette di navigare nella struttura della pagina ed estrarre esattamente il contenuto del tag che ci interessa.

Se non le hai ancora installate, apri il terminale e lancia:

pip install requests beautifulsoup4

💡 Come funziona l'algoritmo?

Il funzionamento del nostro monitor si basa su un ciclo continuo molto semplice:

  1. Download: Effettuiamo una richiesta GET all'URL target.
  2. Parsing: Analizziamo l'HTML con BeautifulSoup per trovare il tag desiderato (es. <div id="stock-status">).
  3. Confronto: Verifichiamo se il valore estratto è diverso da quello memorizzato durante il controllo precedente.
  4. Notifica: Se c'è stato un cambio, inviamo un avviso nel terminale (o via email/Telegram).
  5. Attesa: Mettiamo lo script in "pausa" con un conto alla rovescia prima del controllo successivo.

💻 Il Codice Finale

Ecco lo script completo. Puoi salvarlo in un file chiamato web_monitor.py.


import time
import sys
from datetime import datetime
import requests
from bs4 import BeautifulSoup

# ==========================================
# CONFIGURAZIONE DEL MONITOR
# ==========================================
URL_TARGET = "https://www.example.com"

TAG_NAME = "span"
TAG_ATTRS = {"id": "logo"}  # Es: {"class": "in-stock"} o {"id": "status"}

CHECK_INTERVAL = 300  # Intervallo in secondi (es. 300 sec = 5 minuti)

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}


def get_target_content(url, tag_name, attrs):
    """
    Effettua la richiesta HTTP ed estrae il testo dal tag specificato.
    """
    try:
        response = requests.get(url, headers=HEADERS, timeout=10)
        response.raise_for_status()

        soup = BeautifulSoup(response.text, "html.parser")
        element = soup.find(tag_name, attrs=attrs)

        if element:
            return element.get_text(strip=True)
        else:
            print(f"\n⚠️ [{datetime.now().strftime('%H:%M:%S')}] Tag non trovato nella pagina.")
            return None

    except requests.RequestException as e:
        print(f"\n❌ [{datetime.now().strftime('%H:%M:%S')}] Errore durante la richiesta HTTP: {e}")
        return None


def countdown(seconds):
    """
    Mostra un conto alla rovescia in formato MM:SS sulla stessa riga di terminale.
    """
    for remaining in range(seconds, 0, -1):
        mins, secs = divmod(remaining, 60)
        timer = f"{mins:02d}:{secs:02d}"
        # \r sovrascrive la riga corrente nel terminale
        sys.stdout.write(f"\r⏳ In attesa di un nuovo check tra {timer} ")
        sys.stdout.flush()
        time.sleep(1)

    # Pulisce la riga prima dell'output successivo
    sys.stdout.write("\r" + " " * 50 + "\r")
    sys.stdout.flush()


def start_monitoring():
    """
    Ciclo principale di monitoraggio.
    """
    print(f"🚀 Monitor avviato per: {URL_TARGET}")
    print(f"⏱️ Intervallo di controllo: {CHECK_INTERVAL} secondi\n")

    # Primo controllo per salvare lo stato iniziale
    last_state = get_target_content(URL_TARGET, TAG_NAME, TAG_ATTRS)

    if last_state is None:
        print("Impossibile avviare il monitor: elemento iniziale non trovato o errore HTTP.")
        return

    print(f"📌 Stato iniziale registrato: '{last_state}'\n")

    try:
        while True:
            # Avvia il conto alla rovescia interattivo
            countdown(CHECK_INTERVAL)

            current_time = datetime.now().strftime('%d/%m/%Y %H:%M:%S')
            current_state = get_target_content(URL_TARGET, TAG_NAME, TAG_ATTRS)

            if current_state is None:
                continue

            # Verifichiamo se c'è stato un cambio di stato
            if current_state != last_state:
                print("=" * 50)
                print(f"🔔 NOTIFICA! CAMBIAMENTO RILEVATO [{current_time}]")
                print(f"🔴 Stato precedente: {last_state}")
                print(f"🟢 Nuovo stato:     {current_state}")
                print("=" * 50 + "\n")

                last_state = current_state
            else:
                print(f"✅ [{current_time}] Nessun cambio. Stato attuale: '{current_state}'")

    except KeyboardInterrupt:
        print("\n🛑 Monitor arrestato dall'utente.")


if __name__ == "__main__":
    start_monitoring()

🔍 Come personalizzarlo per il tuo sito target

Per adattare questo script alla pagina che ti interessa, segui questi 3 passaggi:

  1. Apri la pagina su Chrome o Firefox, fai tasto destro sul testo da monitorare e seleziona Ispeziona.
  2. Guarda l'HTML evidenziato nel pannello sviluppatori:
    • Identifica il tipo di tag (es. div, span, p, h1).
    • Cerca una proprietà univoca, come un id o una class.
  3. Aggiorna le variabili TAG_NAME e TAG_ATTRS nel codice Python in base a ciò che hai identificato al punto precedente:
    TAG_NAME = "div"
    TAG_ATTRS = {"class": "badge-disponibilita"}

🎯 Prossimi passi e miglioramenti

Questo script è una solida base di partenza. Se vuoi spingerlo oltre, ecco alcune idee di upgrade:

  • Notifiche Push/Telegram: Invece di stampare solo su terminale, usa le API di Telegram (python-telegram-bot) per farti mandare un messaggio sullo smartphone.
  • Esecuzione in Cloud: Carica lo script su una VPS o su piattaforme come PythonAnywhere per farlo girare H24 senza tenere acceso il PC di casa.
  • Supporto a JavaScript: Se il sito carica i dati tramite AJAX/React, requests potrebbe non vedere il contenuto finale. In quel caso, valuta l'uso di Playwright o Selenium.


Techelopment ha già pensato a tutto 😊

👉 Il programma completo (site_monitoring.py) mostrato nell’articolo è disponibile su GitHub, così da poter essere scaricato, eseguito e adattato facilmente alle proprie esigenze.


Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment