Actualiser une page produit et copier des chiffres dans un tableur fonctionne jusqu'à ce que vous suiviez plus d'une poignée d'articles. C'est lent, facile à oublier, et pire encore, cela vous dit quel est un prix maintenant mais rien sur le fait qu'il ait bougé, de combien, ou si cela importe. Le signal intéressant dans les données produits est le changement, pas l'instantané, et vous ne voyez le changement que si vous collectez les mêmes champs selon un calendrier et les comparez dans le temps.

Ce guide construit un petit outil de surveillance produit avec IA fonctionnel en Python. Il scrape des pages produits publiques selon un minuteur avec Crawlbase, stocke chaque lecture, compare la nouvelle lecture à la dernière pour détecter les mouvements significatifs de prix, de stock et de note, puis confie ces changements à un LLM qui rédige une courte alerte en langage naturel. Tout ici reste sur les données publiques de produits : les prix, la disponibilité et les notes que tout visiteur voit sans se connecter. Pas de comptes, pas de paniers, pas de données personnelles.

Ce que fait l'outil, de bout en bout

Pensez au système comme à un relais à quatre stations. Premièrement, Crawlbase récupère une page produit et renvoie des champs structurés propres pour que vous n'ayez pas à analyser du HTML fragile à la main. Deuxièmement, chaque lecture est écrite dans un store local avec un horodatage, ce qui vous donne l'historique dont dépend la détection des changements. Troisièmement, une étape de diff compare la dernière lecture à la précédente et décide si quelque chose a suffisamment bougé pour mériter attention. Quatrièmement, lorsqu'il y a un vrai changement, un LLM transforme les chiffres bruts avant/après en un résumé d'une ligne que vous pouvez déposer dans Slack, un email ou un journal.

La boucle de planification enveloppe les quatre pour que l'ensemble tourne automatiquement, une fois par heure ou une fois par jour, sans que vous la regardiez. Cette boucle est la partie qui transforme un scraping ponctuel en véritable surveillance. La même forme sous-tend la plupart des travaux de web scraping ecommerce : collecter, stocker, comparer, agir.

Prérequis

Vous n'avez pas besoin d'être un expert, mais un peu de préparation aide. Vous devez être à l'aise pour lire et modifier un script Python, envoyer une requête HTTP et vérifier le JSON qui revient, et exécuter un fichier depuis votre terminal. Une idée approximative de la façon dont un LLM répond à une invite structurée est utile pour l'étape de résumé, bien que le code gère le câblage pour vous.

Côté outillage vous avez besoin de trois choses : Python 3.9 ou plus récent installé localement, un compte Crawlbase avec un token API, et une clé API pour le LLM que vous utilisez pour l'étape de résumé (l'exemple utilise un point de terminaison compatible OpenAI, que la plupart des fournisseurs exposent). Les nouveaux comptes Crawlbase incluent jusqu'à 20 000 requêtes gratuites : 1 000 à l'inscription, et davantage à mesure que vous complétez les étapes d'onboarding, ce qui est largement suffisant pour construire et tester ceci sur quelques vrais produits.

Configurer le projet

Créez un dossier, un environnement virtuel, et installez les deux bibliothèques sur lesquelles s'appuie l'outil : le client Crawlbase pour le scraping et le client openai pour l'étape de résumé (il parle à n'importe quelle API compatible OpenAI).

bash
python --version

mkdir product-monitor && cd product-monitor
python -m venv .venv
source .venv/bin/activate
pip install crawlbase openai

Gardez les deux clés hors du code. Lisez-les depuis des variables d'environnement pour qu'aucun secret ne se retrouve dans un commit. Définissez-les une fois dans votre shell avant d'exécuter quoi que ce soit.

bash
export CRAWLBASE_TOKEN="your_crawlbase_token"
export LLM_API_KEY="your_llm_api_key"

Étape 1 : Collecter les données produit avec Crawlbase

La première station récupère une page produit et renvoie les champs qui nous intéressent. Le chemin le plus propre pour un store pris en charge est la Crawling API, qui exécute un parseur maintenu côté serveur et vous remet du JSON structuré plutôt que du HTML brut. Vous appelez le même point de terminaison que la Crawling API et ajoutez un paramètre scraper nommant le parseur souhaité. Enregistrez ceci sous collect.py.

python
import os
from crawlbase import ScraperAPI

scraper = ScraperAPI({"token": os.environ["CRAWLBASE_TOKEN"]})

def collect_product(url):
    # 'amazon-product-details' is one of the maintained parsers.
    response = scraper.get(url, {"scraper": "amazon-product-details"})
    body = response["json"]["body"]

    reading = {
        "url": url,
        "name": body.get("name"),
        "price": body.get("rawPrice"),
        "currency": body.get("currency"),
        "in_stock": body.get("inStock"),
        "rating": body.get("rating"),
    }

    if reading["price"] is None or reading["name"] is None:
        raise ValueError(f"Parse returned no price/name for {url}")

    return reading

Si le store que vous suivez n'est pas l'un des parseurs pris en charge, passez à la Crawling API et analysez le HTML vous-même, ou générez un extracteur spécifique à la cible. Dans tous les cas, Crawlbase gère la partie difficile de la requête : il fait tourner les adresses IP, gère les en-têtes et rend JavaScript lorsqu'une page en a besoin, vous obtenez donc une vraie réponse au lieu d'une page de blocage.

Rendu normal ou JS

La Scraper API et la Crawling API font par défaut une récupération statique rapide. Si une page produit rend son prix ou son stock côté client (courant sur les storefronts modernes), passez "ajax_wait": "true" et un "page_wait" en millisecondes pour que le contenu se charge avant que le HTML ne revienne. Commencez à 5000 ms et augmentez si un champ revient vide.

Étape 2 : Stocker chaque lecture avec un horodatage

La détection des changements a besoin de mémoire, chaque lecture va donc sur disque avec l'heure à laquelle elle a été prise. Un seul fichier SQLite suffit et maintient l'outil léger en dépendances. Enregistrez ceci sous store.py.

python
import sqlite3
from datetime import datetime, timezone

DB = "readings.db"

def init_db():
    con = sqlite3.connect(DB)
    con.execute(
        """CREATE TABLE IF NOT EXISTS readings (
            url TEXT, name TEXT, price REAL, currency TEXT,
            in_stock INTEGER, rating REAL, taken_at TEXT)"""
    )
    con.commit()
    con.close()

def save_reading(r):
    con = sqlite3.connect(DB)
    con.execute(
        "INSERT INTO readings VALUES (?, ?, ?, ?, ?, ?, ?)",
        (r["url"], r["name"], r["price"], r["currency"],
         int(bool(r["in_stock"])), r["rating"],
         datetime.now(timezone.utc).isoformat()),
    )
    con.commit()
    con.close()

def last_two(url):
    con = sqlite3.connect(DB)
    con.row_factory = sqlite3.Row
    rows = con.execute(
        "SELECT * FROM readings WHERE url = ? ORDER BY taken_at DESC LIMIT 2",
        (url,),
    ).fetchall()
    con.close()
    return [dict(row) for row in rows]

last_two renvoie la lecture la plus récente et celle d'avant, ce qui est tout ce dont l'étape de diff a besoin. Si vous voulez un historique complet des prix pour les graphiques plus tard, la table contient déjà chaque ligne ; il suffit de les sélectionner toutes pour une URL ordonnées par taken_at.

Étape 3 : Détecter les changements significatifs

C'est là que la plupart des moniteurs naïfs se trompent : ils alertent sur chaque petit frémissement, vous les ignorez donc en une journée. La solution est un seuil. Traitez un mouvement de prix comme un changement seulement s'il franchit un pourcentage que vous définissez, et signalez toujours les choses qui sont binaires, comme un produit qui passe en rupture de stock. Enregistrez ceci sous detect.py.

python
PRICE_THRESHOLD = 0.03  # 3% move counts as meaningful

def detect_changes(current, previous):
    changes = []

    old_price, new_price = previous["price"], current["price"]
    if old_price and new_price:
        delta = (new_price - old_price) / old_price
        if abs(delta) >= PRICE_THRESHOLD:
            changes.append({
                "field": "price",
                "old": old_price,
                "new": new_price,
                "pct": round(delta * 100, 1),
            })

    if previous["in_stock"] != current["in_stock"]:
        changes.append({
            "field": "in_stock",
            "old": bool(previous["in_stock"]),
            "new": bool(current["in_stock"]),
        })

    if previous["rating"] and current["rating"]:
        if abs(current["rating"] - previous["rating"]) >= 0.2:
            changes.append({
                "field": "rating",
                "old": previous["rating"],
                "new": current["rating"],
            })

    return changes

Ajustez les seuils au produit. Un produit de base qui fluctue de quelques centimes toute la journée nécessite une bande de prix plus large ; un article de prix élevé où une baisse de 3 % représente de l'argent réel nécessite une bande plus étroite. L'essentiel est que la règle vit dans du code lisible que vous pouvez lire et ajuster, non enfouie dans le jugement d'un modèle.

Crawlbase Crawling API

Le moniteur n'est aussi fiable que les données qui l'alimentent. La Scraper API renvoie des champs produits structurés propres depuis les stores pris en charge, avec la rotation d'adresses IP, la gestion des en-têtes et le rendu JavaScript gérés côté serveur, une tâche planifiée continue donc à renvoyer de vraies lectures au lieu de pages de blocage. Pointez-la vers une page produit publique sur le niveau gratuit et construisez la boucle autour d'elle.

Étape 4 : Résumer et alerter avec un LLM

Une liste de dicts de changements est correcte mais pas lisible d'un coup d'œil. Le rôle du LLM ici est étroit et c'est délibéré : transformer les changements structurés en une courte phrase précise. Maintenir le modèle sur une entrée structurée et serrée est ce qui l'empêche de dériver ou d'inventer des détails. Enregistrez ceci sous alert.py.

python
import os
import json
from openai import OpenAI

client = OpenAI(api_key=os.environ["LLM_API_KEY"])

def summarize_changes(product_name, changes):
    prompt = (
        f"Product: {product_name}\n"
        f"Detected changes (JSON): {json.dumps(changes)}\n\n"
        "Write one short sentence summarizing what changed. "
        "State only what the data shows. Do not speculate or "
        "add numbers that are not present."
    )

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system",
             "content": "You summarize product data changes factually."},
            {"role": "user", "content": prompt},
        ],
        temperature=0.1,
    )
    return response.choices[0].message.content.strip()

def send_alert(message):
    # Swap this for Slack, email, or a webhook in production.
    print(f"[ALERT] {message}")

Une temperature basse et une instruction de n'indiquer que ce que les données montrent maintiennent le résumé lié aux chiffres que vous avez passés. Si vous préférez ne pas dépendre d'un modèle hébergé, routez le même appel via un point de terminaison compatible OpenAI auto-hébergé ou alternatif en changeant l'URL de base du client ; le reste de la fonction est inchangé. Pour délivrer l'alerte pour de vrai, remplacez le print dans send_alert par un post webhook Slack ou un envoi d'email.

Étape 5 : Câbler la boucle ensemble

Connectez maintenant les quatre stations en une seule passe sur votre liste de surveillance. Chaque exécution collecte une lecture fraîche, la sauvegarde, la compare à la lecture précédente, et n'alerte que lorsque le diff trouve quelque chose. Enregistrez ceci sous monitor.py.

python
from collect import collect_product
from store import init_db, save_reading, last_two
from detect import detect_changes
from alert import summarize_changes, send_alert

WATCHLIST = [
    "https://www.example-store.com/product/abc",
    "https://www.example-store.com/product/xyz",
]

def run_once():
    init_db()
    for url in WATCHLIST:
        try:
            reading = collect_product(url)
        except Exception as exc:
            print(f"Skipped {url}: {exc}")
            continue

        save_reading(reading)
        history = last_two(url)
        if len(history) < 2:
            continue  # first reading, nothing to compare

        current, previous = history[0], history[1]
        changes = detect_changes(current, previous)
        if changes:
            summary = summarize_changes(reading["name"], changes)
            send_alert(summary)

if __name__ == "__main__":
    run_once()

Exécutez-le deux fois avec un intervalle entre les deux (ou alimentez la table avec deux lectures) et vous verrez l'alerte se déclencher lorsque quelque chose a bougé. Une seule passe contre un produit stable n'imprime rien, ce qui est exactement ce que vous voulez : silence sauf s'il y a des nouvelles.

bash
python monitor.py
# [ALERT] The price of "Acme Widget" dropped 7.4% from $129 to $119, and it is back in stock.

Étape 6 : Planifier l'exécution

Surveiller signifie tourner sur un minuteur sans que vous tapiez la commande. Ne faites pas de boucle infinie dans le processus Python et n'appelez pas sleep ; cela meurt dès que la machine redémarre et ne vous donne aucun journal. Confiez le calendrier à votre système d'exploitation à la place. Sur Linux ou macOS, une entrée cron qui exécute le script toutes les heures ressemble à ceci.

bash
# crontab -e, then add (runs at the top of every hour):
0 * * * * cd /path/to/product-monitor && .venv/bin/python monitor.py >> monitor.log 2>&1

Sur Windows, le Planificateur de tâches fait le même travail : pointez une tâche de base vers l'exécutable Python à l'intérieur de votre environnement virtuel avec monitor.py comme argument et définissez le déclencheur sur l'intervalle de votre choix. Dans tous les cas, choisissez une cadence qui correspond à la rapidité avec laquelle les données bougent réellement. Horaire convient pour les prix qui évoluent rapidement ; une fois par jour suffit pour le stock et les notes, et c'est plus économe en requêtes.

À mesure que votre liste de surveillance dépasse une poignée de produits, une boucle synchrone qui récupère une URL à la fois commence à traîner. À ce stade, passez la collecte au Crawler asynchrone, qui pousse les résultats vers un webhook au fur et à mesure que les pages se terminent pour que vous ne bloqueez pas sur chaque requête. Pour la stratégie plus large derrière le suivi des prix des concurrents dans le temps, le web scraping pour l'intelligence des prix couvre le pourquoi ; le scraping ecommerce à grande échelle couvre la façon dont le même pipeline tient à volume.

Maintenir le flux de données

Un scraper planifié est un scraper qui doit continuer à fonctionner sans surveillance, la couche de données est donc là où la fiabilité compte le plus. Crawlbase fait déjà tourner les adresses IP et gère les en-têtes derrière chaque requête, ce qui maintient une tâche répétée sans qu'elle soit signalée comme bot. Si vous avez besoin d'un contrôle plus fin du routage, ou si vous voulez envoyer votre propre client HTTP via un pool rotatif, le Smart AI Proxy expose le même réseau comme point de terminaison proxy standard. Surveillez vos journaux d'exécution pour les codes de statut qui s'éloignent du succès : une soudaine série de challenges ou d'erreurs est le signal de ralentir votre cadence ou d'élargir la rotation, non de réessayer plus fort.

Récapitulatif

Points clés

  • Surveillez le changement, pas l'instantané. La valeur est dans la comparaison des lectures dans le temps, ce qui signifie que vous devez stocker chaque lecture avec un horodatage.
  • Crawlbase est la couche de données fiable. La Crawling API renvoie des champs structurés propres, et la rotation d'adresses IP plus le rendu empêchent qu'une tâche planifiée soit bloquée.
  • Utilisez un seuil pour détecter les mouvements significatifs. Une bande en pourcentage sur le prix plus des vérifications binaires sur le stock maintiennent les alertes comme signal, non comme bruit.
  • Gardez le LLM étroit. Alimentez-le avec le diff structuré, demandez une phrase factuelle à basse température, et il résume au lieu d'inventer.
  • Laissez le système d'exploitation le planifier. Cron ou le Planificateur de tâches bat une boucle sleep intégrée au processus ; choisissez une cadence qui correspond à la rapidité avec laquelle les données bougent.
  • Restez sur les données publiques. Prix, stock et notes uniquement ; pas de comptes, paniers ou données personnelles.

Foire aux questions

Qu'est-ce qu'un outil de surveillance produit avec IA ?

C'est un programme qui surveille des pages produits publiques selon un calendrier, enregistre des champs clés comme le prix, le stock et la note à chaque fois, et utilise un modèle IA pour signaler et expliquer les changements significatifs. La couche de scraping maintient le flux de données fiable, et la couche IA transforme les chiffres bruts avant/après en une courte alerte lisible pour que vous agissiez sur ce qui a bougé plutôt que de lire des tableurs.

Ai-je besoin de la Crawling API ou de la Scraper API pour ceci ?

Utilisez la Scraper API lorsque le store que vous suivez est l'un des parseurs maintenus, car elle renvoie directement des champs produits structurés et vous évite d'écrire du code d'extraction. Utilisez la Crawling API lorsque vous avez besoin du HTML brut à analyser vous-même ou lorsque la page n'est pas couverte par un parseur. Les deux partagent le même réseau, la rotation d'adresses IP et le rendu fonctionnent donc dans les deux cas ; la différence est uniquement de savoir si Crawlbase analyse la page pour vous.

Comment l'outil décide-t-il ce qui constitue un changement significatif ?

Par des seuils que vous définissez dans du code lisible, non par le jugement du modèle. L'exemple traite un mouvement de prix comme significatif seulement lorsqu'il franchit une bande de pourcentage (3 % par défaut), signale toujours un produit qui passe en stock ou en rupture, et signale un changement de note de 0,2 ou plus. Resserrer ou assouplir ces chiffres par produit est la façon dont vous gardez les alertes utiles plutôt que constantes.

Est-ce que l'IA va halluciner des chiffres lorsqu'elle rédige l'alerte ?

Le risque est réel avec des invites ouvertes, c'est pourquoi l'étape de résumé est maintenue étroite. Le modèle reçoit uniquement le diff structuré, tourne à une basse température, et reçoit l'instruction d'indiquer uniquement ce que les données montrent et de ne pas ajouter de chiffres qui ne sont pas présents. Cette structure est ce qui maintient la phrase liée à vos lectures réelles plutôt qu'à des détails inventés.

Que se passe-t-il lorsqu'un store modifie la mise en page de sa page ?

Si vous utilisez la Crawling API, le parseur maintenu absorbe la plupart des changements de mise en page pour vous, ce qui est l'une des raisons pour lesquelles il vaut la peine de l'utiliser lorsqu'il est disponible. Si vous analysez vous-même le HTML via la Crawling API, un changement de mise en page peut casser vos sélecteurs, et la correction consiste à réinspecter la page en direct et à les mettre à jour. Comme Crawlbase renvoie toujours la page complète, vous ajustez la logique d'analyse plutôt que de reconstruire la requête.

À quelle fréquence le moniteur doit-il tourner ?

Adaptez la cadence à la rapidité avec laquelle les données bougent et à votre budget de requêtes. Horaire convient pour les prix qui changent rapidement ; une fois par jour suffit pour le stock et les notes et utilise bien moins de requêtes. Planifier via cron ou le Planificateur de tâches Windows vous permet de définir l'intervalle par tâche, et vous pouvez faire tourner différents produits à des taux différents si certains comptent plus que d'autres.

Commencer à construire

Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.

Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.

En libre-service · Sans appel commercial requis · Volumes de crawl entreprise disponibles