📑 Table des matières

Scraping intelligent avec l'IA

Automatisation 🟡 Intermédiaire ⏱️ 15 min de lecture 📅 2026-02-24

Le web scraping a longtemps été un exercice de patience : inspecter le HTML, écrire des sélecteurs CSS fragiles, gérer les pages dynamiques en JavaScript, et tout recommencer quand le site change sa structure. L'IA change complètement la donne. Au lieu de parser du HTML, on peut maintenant comprendre la page et en extraire les informations de manière intelligente.

Dans ce guide, on explore le scraping assisté par IA : comment ça marche, quels outils utiliser, des exemples concrets, et les considérations éthiques et légales à connaître.


🔄 Scraping classique vs scraping IA

Le scraping classique : fragile et laborieux

Le scraping traditionnel repose sur l'analyse de la structure HTML :

# Scraping classique avec BeautifulSoup
import requests
from bs4 import BeautifulSoup

response = requests.get("https://example.com/produits")
soup = BeautifulSoup(response.text, "html.parser")

produits = []
for card in soup.select("div.product-card"):
    nom = card.select_one("h3.product-title").text.strip()
    prix = card.select_one("span.price").text.strip()
    produits.append({"nom": nom, "prix": prix})

# ❌ Problèmes :
# - Si le site change "div.product-card" → tout casse
# - Pages JavaScript → requests ne suffit pas
# - Données dans des formats variés → regex fragiles
# - Anti-bot → headers, cookies, captchas

Le scraping IA : comprendre au lieu de parser

Le scraping IA utilise un LLM pour comprendre le contenu de la page, pas sa structure HTML :

# Scraping IA : le LLM comprend la page
from openai import OpenAI

client = OpenAI()

# On récupère le texte de la page (pas besoin de parser le HTML)
page_content = fetch_page_as_text("https://example.com/produits")

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": """Extrais tous les produits 
        de cette page. Pour chaque produit, donne :
        - nom, prix, description, disponibilité
        Réponds en JSON."""},
        {"role": "user", "content": page_content}
    ],
    response_format={"type": "json_object"}
)

produits = json.loads(response.choices[0].message.content)
# ✅ Fonctionne même si la structure HTML change
# ✅ Comprend le contexte ("en rupture", "promo -30%")
# ✅ Extrait des infos implicites

Comparaison détaillée

Aspect Scraping classique Scraping IA
Robustesse ⭐⭐ Casse si le HTML change ⭐⭐⭐⭐⭐ Comprend le contenu
Vitesse ⭐⭐⭐⭐⭐ Très rapide ⭐⭐⭐ Plus lent (appel LLM)
Coût ⭐⭐⭐⭐⭐ Quasi gratuit ⭐⭐⭐ Coût API LLM
Précision ⭐⭐⭐⭐ Si bien codé ⭐⭐⭐⭐ Très bon sur données textuelles
Données structurées ⭐⭐⭐ Demande du travail ⭐⭐⭐⭐⭐ JSON natif
Setup ⭐⭐ Lent (sélecteurs, debug) ⭐⭐⭐⭐⭐ Rapide (prompt + go)
Maintenance ⭐⭐ Casse régulièrement ⭐⭐⭐⭐ Rarement besoin de MAJ
Volume ⭐⭐⭐⭐⭐ Millions de pages ⭐⭐⭐ Limité par coûts/rate limits

💡 La meilleure approche : combiner les deux. Utilisez le scraping classique pour récupérer le contenu brut rapidement, puis l'IA pour l'extraire et le structurer intelligemment.


🛠️ Les outils du scraping IA

1. web_fetch + LLM : la méthode simple

La méthode la plus directe : récupérer le contenu d'une page en texte/markdown, puis le faire analyser par un LLM.

import httpx
from openai import OpenAI

client = OpenAI()

# Étape 1 : Récupérer la page en texte lisible
# (en utilisant un service comme Jina Reader ou un extracteur markdown)
response = httpx.get(
    "https://r.jina.ai/https://example.com/article",
    headers={"Accept": "text/markdown"}
)
page_markdown = response.text

# Étape 2 : Extraire les données avec le LLM
extraction = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": """Tu es un extracteur de données.
        Extrais les informations demandées au format JSON.
        Si une info n'est pas trouvée, mets null."""},
        {"role": "user", "content": f"""Page web :
{page_markdown}

Extrais : titre, auteur, date, résumé (2 phrases), tags"""}
    ]
)
print(extraction.choices[0].message.content)

Si vous utilisez OpenClaw, l'outil web_fetch est intégré nativement :

# OpenClaw peut directement fetch + analyser
# L'agent utilise web_fetch puis le LLM pour structurer
User: "Récupère les 5 derniers articles de TechCrunch sur l'IA"
# → OpenClaw fetch la page, extrait, structure en JSON

2. Browser automation + IA : pour les sites dynamiques

Pour les sites qui nécessitent JavaScript, scroll, clics, ou authentification :

from playwright.sync_api import sync_playwright
from openai import OpenAI

client = OpenAI()

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()

    # Navigation comme un humain
    page.goto("https://example.com/search")
    page.fill("#search-input", "intelligence artificielle")
    page.click("button[type=submit]")
    page.wait_for_selector(".results")

    # Scroll pour charger plus de résultats
    for _ in range(3):
        page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
        page.wait_for_timeout(2000)

    # Récupérer le contenu visible
    content = page.inner_text("body")

    # IA pour extraire les données structurées
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """Extrais tous les résultats 
            de recherche. Format JSON : [{title, url, snippet, date}]"""},
            {"role": "user", "content": content}
        ]
    )

    browser.close()

OpenClaw intègre un browser automation complet qui peut naviguer, cliquer, remplir des formulaires et extraire des données automatiquement :

# OpenClaw browser automation
# L'agent peut contrôler un navigateur + comprendre les pages
User: "Va sur LinkedIn, cherche les profils 'data engineer Paris'"
# → OpenClaw ouvre le browser, navigue, extrait les profils

3. API + LLM : la méthode propre

Avant de scraper, vérifiez toujours s'il existe une API ! Beaucoup de sites en proposent :

# Méthode propre : API + LLM pour structurer
import httpx
from openai import OpenAI

client = OpenAI()

# API publique (exemple : Hacker News)
stories = httpx.get(
    "https://hacker-news.firebaseio.com/v0/topstories.json"
).json()[:10]

articles = []
for story_id in stories:
    story = httpx.get(
        f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json"
    ).json()
    articles.append(story)

# LLM pour analyser et catégoriser
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": """Analyse ces articles tech.
        Pour chacun, ajoute : catégorie (IA, web, hardware, autre),
        pertinence (1-10), résumé en 1 phrase."""},
        {"role": "user", "content": json.dumps(articles, indent=2)}
    ]
)

4. Vision models : scraper des images et captures d'écran

Les modèles vision peuvent « lire » des captures d'écran — utile pour les sites très visuels ou anti-scraping :

import base64
from openai import OpenAI
from playwright.sync_api import sync_playwright

client = OpenAI()

# Capture d'écran de la page
with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com/dashboard")
    screenshot = page.screenshot()  # bytes PNG
    browser.close()

# Envoyer au modèle vision
b64_image = base64.b64encode(screenshot).decode()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Extrais toutes les données "
             "de ce dashboard : métriques, graphiques, tableaux. "
             "Format JSON structuré."},
            {"type": "image_url", "image_url": {
                "url": f"data:image/png;base64,{b64_image}"
            }}
        ]
    }]
)

📋 Exemples concrets

Exemple 1 : Veille concurrentielle

Surveillez automatiquement les prix et offres de vos concurrents :

import json
import httpx
from openai import OpenAI
from datetime import datetime

client = OpenAI()

CONCURRENTS = [
    {"nom": "Concurrent A", "url": "https://concurrent-a.com/pricing"},
    {"nom": "Concurrent B", "url": "https://concurrent-b.com/tarifs"},
    {"nom": "Concurrent C", "url": "https://concurrent-c.com/plans"},
]

Pour aller plus loin sur ce sujet, consultez notre guide [Cron + IA : automatiser des tâches intelligentes 24/7](/article/cron-ia-automatiser-taches-intelligentes).

def analyser_pricing(nom: str, url: str) -> dict:
    """Scrape et analyse la page pricing d'un concurrent."""
    # Récupérer le contenu
    resp = httpx.get(f"https://r.jina.ai/{url}")

    # Extraction IA
    analysis = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """Analyse cette page pricing.
            Extrais au format JSON :
            {
              "plans": [{"nom": str, "prix_mensuel": float, 
                         "prix_annuel": float, "features": [str]}],
              "offre_speciale": str ou null,
              "essai_gratuit": bool,
              "changements_notables": str ou null
            }"""},
            {"role": "user", "content": resp.text[:8000]}
        ]
    )

    result = json.loads(analysis.choices[0].message.content)
    result["concurrent"] = nom
    result["date_analyse"] = datetime.now().isoformat()
    return result

Pour aller plus loin sur ce sujet, consultez notre guide [Générer du contenu automatiquement avec l'IA](/article/generer-contenu-automatiquement-ia).

# Lancer l'analyse
rapport = [analyser_pricing(c["nom"], c["url"]) for c in CONCURRENTS]

# Sauvegarder
with open(f"veille_{datetime.now():%Y-%m-%d}.json", "w") as f:
    json.dump(rapport, f, indent=2, ensure_ascii=False)

Exemple 2 : Agrégation d'actualités

Créez votre propre flux d'actualités IA personnalisé :

import feedparser
from openai import OpenAI

client = OpenAI()

SOURCES = [
    "https://techcrunch.com/feed/",
    "https://www.theverge.com/rss/index.xml",
    "https://feeds.arstechnica.com/arstechnica/index",
]

def agreger_actualites(sujet: str = "intelligence artificielle"):
    articles = []

    for feed_url in SOURCES:
        feed = feedparser.parse(feed_url)
        for entry in feed.entries[:10]:
            articles.append({
                "titre": entry.title,
                "lien": entry.link,
                "source": feed.feed.title,
                "date": entry.get("published", ""),
                "resume": entry.get("summary", "")[:500]
            })

    # Filtrage et analyse par IA
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": f"""Tu es un curateur d'actualités.
            Parmi les articles suivants, sélectionne ceux qui concernent 
            "{sujet}". Pour chaque article retenu :
            - Résumé en 2 phrases en français
            - Score de pertinence (1-10)
            - Tags (3 max)

            Trie par pertinence décroissante. Format JSON."""},
            {"role": "user", "content": json.dumps(articles, ensure_ascii=False)}
        ]
    )

    return json.loads(response.choices[0].message.content)

# Utilisation
news = agreger_actualites("intelligence artificielle")
for article in news[:5]:
    print(f"📰 {article['titre']}")
    print(f"   {article['resume']}")
    print(f"   Pertinence: {article['score']}/10")
    print()

Exemple 3 : Monitoring de prix

Surveillez les prix de produits et recevez des alertes :

import json
import sqlite3
from datetime import datetime
import httpx
from openai import OpenAI

client = OpenAI()

def surveiller_prix(url: str, produit: str) -> dict:
    """Récupère et analyse le prix d'un produit."""
    resp = httpx.get(f"https://r.jina.ai/{url}")

    extraction = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """Extrais les informations 
            de prix de cette page produit. Format JSON :
            {
              "prix_actuel": float,
              "prix_barre": float ou null,
              "devise": "EUR",
              "en_stock": bool,
              "promotion": str ou null,
              "vendeur": str
            }"""},
            {"role": "user", "content": f"Produit recherché: {produit}"
             f"\n\nPage:\n{resp.text[:6000]}"}
        ]
    )

    data = json.loads(extraction.choices[0].message.content)
    data["url"] = url
    data["produit"] = produit
    data["timestamp"] = datetime.now().isoformat()
    return data

def verifier_alerte(prix_actuel: float, prix_cible: float) -> bool:
    """Vérifie si le prix est passé sous le seuil."""
    return prix_actuel <= prix_cible

# Exemple d'utilisation
produits_suivis = [
    {"url": "https://amazon.fr/dp/XXXXX", "nom": "GPU RTX 5080", "prix_cible": 900},
    {"url": "https://fnac.com/a123456", "nom": "MacBook Air M4", "prix_cible": 1100},
]

for produit in produits_suivis:
    data = surveiller_prix(produit["url"], produit["nom"])
    if verifier_alerte(data["prix_actuel"], produit["prix_cible"]):
        print(f"🚨 ALERTE: {produit['nom']} à {data['prix_actuel']}€ "
              f"(cible: {produit['prix_cible']}€)")

🔄 Automatiser le scraping avec OpenClaw

OpenClaw est particulièrement puissant pour le scraping IA car il combine nativement :
- web_fetch : récupération de pages en markdown
- Browser automation : navigation complète (JS, clics, formulaires)
- LLM intégré : analyse et extraction automatique
- Cron jobs : exécution planifiée

# Exemple : veille automatique quotidienne avec OpenClaw
# L'agent peut être configuré pour :
# 1. Chaque matin à 8h, scraper vos sources
# 2. Extraire et catégoriser les informations
# 3. Vous envoyer un résumé par Telegram/Discord

# Configuration cron dans OpenClaw
# Voir : configurer les tâches planifiées

Pour mettre en place ce type d'automatisation, consultez :
- Installer OpenClaw sur un VPS pour un agent toujours actif
- Configurer OpenClaw pour paramétrer les tâches automatiques
- Automatiser sa vie avec l'IA pour d'autres idées d'automatisation


⚖️ Éthique et légalité du scraping

Le scraping n'est ni totalement légal ni totalement illégal. Ça dépend de plusieurs facteurs :

Facteur Légal ✅ Risqué ⚠️ Illégal ❌
Données Publiques, non personnelles Publiques mais personnelles Privées, derrière login
Usage Recherche, usage personnel Commercial, agrégation Revente, spam
Volume Raisonnable Intensif DoS / surcharge serveur
robots.txt Respecté Partiellement respecté Ignoré
CGU du site Conformes Zone grise Violation explicite
Région Variable RGPD (données perso) CFAA (USA, accès non autorisé)

Les règles d'or du scraping éthique

# Bonnes pratiques de scraping éthique

import time
import httpx

class EthicalScraper:
    def __init__(self, delay: float = 2.0):
        self.delay = delay
        self.session = httpx.Client(
            headers={
                # 1. S'identifier clairement
                "User-Agent": "MonBot/1.0 ([email protected]; "
                              "recherche académique)",
            },
            timeout=30,
            follow_redirects=True,
        )

    def respecte_robots_txt(self, url: str) -> bool:
        """Vérifie robots.txt avant de scraper."""
        from urllib.robotparser import RobotFileParser
        from urllib.parse import urlparse

        parsed = urlparse(url)
        robots_url = f"{parsed.scheme}://{parsed.netloc}/robots.txt"

        rp = RobotFileParser()
        rp.set_url(robots_url)
        rp.read()
        return rp.can_fetch("MonBot", url)

    def fetch(self, url: str) -> str | None:
        # 2. Respecter robots.txt
        if not self.respecte_robots_txt(url):
            print(f"⛔ Bloqué par robots.txt : {url}")
            return None

        # 3. Rate limiting (ne pas surcharger)
        time.sleep(self.delay)

        response = self.session.get(url)

        # 4. Respecter les codes HTTP
        if response.status_code == 429:  # Too Many Requests
            print("⏳ Rate limited, attente...")
            time.sleep(60)
            return self.fetch(url)

        if response.status_code != 200:
            return None

        return response.text

Checklist avant de scraper

# ✅ Checklist scraping éthique

☐ Vérifié robots.txt du site
☐ Lu les CGU / ToS du site
☐ Pas de données personnelles (ou RGPD respecté)
☐ Rate limiting implémenté (min 1-2 sec entre requêtes)
☐ User-Agent identifiant avec contact
☐ API officielle vérifiée (préférer si disponible)
☐ Usage légitime (recherche, veille, pas de revente)
☐ Pas de contournement de protection (captcha, login)
☐ Stockage sécurisé des données collectées
☐ Politique de rétention définie (pas de stockage infini)

RGPD et données personnelles

Si vous scrapez des données contenant des informations personnelles (noms, emails, photos...) en Europe, le RGPD s'applique :

  • Base légale nécessaire (intérêt légitime, consentement...)
  • Droit à l'effacement : les personnes peuvent demander la suppression
  • Minimisation : ne collectez que ce qui est nécessaire
  • Sécurité : protégez les données collectées
  • DPO : désignez un responsable si traitement à grande échelle

Alternatives au scraping

Avant de scraper, explorez ces alternatives :

Alternative Avantage
API officielle Légal, structuré, stable
Datasets publics Prêt à l'emploi, souvent gratuit
Partenariats data Accès légal à des données premium
RSS/Atom feeds Flux d'actualités structurés
Common Crawl Archive web ouverte (pétaoctets)
Data marketplaces Données pré-scrapées, légales

🚀 Architecture d'un système de scraping IA

Pour un projet de scraping IA en production, voici l'architecture recommandée :

┌──────────────────────────────────────────────────┐
                  ORCHESTRATEUR                    
            (Cron / OpenClaw / Airflow)            
└──────────────┬───────────────────┬───────────────┘
                                  
       ┌───────▼───────┐   ┌──────▼────────┐
          COLLECTE          COLLECTE    
         (web_fetch)       (browser)    
         Sites simples     Sites JS/SPA 
       └───────┬───────┘   └──────┬────────┘
                                  
               └─────────┬─────────┘
                          HTML/Markdown brut
                ┌────────▼────────┐
                   EXTRACTION    
                  (LLM / GPT-4o 
                   mini)         
                └────────┬────────┘
                          JSON structuré
                ┌────────▼────────┐
                   STOCKAGE      
                  (PostgreSQL /  
                   SQLite)       
                └────────┬────────┘
                         
              ┌──────────┼──────────┐
                                  
       ┌──────▼──┐ ┌────▼────┐ ┌──▼───────┐
        ALERTES   ANALYSE   DASHBOARD
        (email,   (trends,  (Grafana,
        Telegram)   LLM)      custom) 
       └─────────┘ └─────────┘ └──────────┘

Estimation des coûts

Composant Volume Coût mensuel
web_fetch (100 pages/jour) 3 000 pages/mois ~$0 (self-hosted)
LLM extraction (GPT-4o mini) 3 000 appels × 2K tokens ~$1.50
Browser automation (si nécessaire) Serveur + Playwright ~$5-10
Stockage (SQLite/PostgreSQL) < 1 GB ~$0
Total ~$5-15/mois

Pour un monitoring de prix sur 50 produits, 3 fois par jour, le coût IA est d'environ $5/mois — bien moins qu'un abonnement à un service de monitoring commercial.


🎯 Résumé et bonnes pratiques

Principe Détail
Commencez simple web_fetch + LLM avant le browser automation
API d'abord Cherchez toujours une API officielle avant de scraper
Modèle économique GPT-4o mini ou Haiku pour l'extraction (pas besoin d'Opus)
Rate limiting Minimum 1-2 secondes entre les requêtes
robots.txt Toujours respecter, c'est la base
Structured output Demandez du JSON pour des données propres
Monitoring Surveillez vos coûts et la qualité d'extraction
Éthique Si vous ne voudriez pas qu'on le fasse sur votre site, ne le faites pas

Le scraping IA rend accessible à tous ce qui nécessitait auparavant des développeurs spécialisés. Avec un LLM et quelques lignes de code, vous pouvez extraire, structurer et analyser des données web de manière fiable et maintenable.

Mais n'oubliez pas : avec un grand pouvoir vient une grande responsabilité. Scrapez de manière éthique, respectez les sites et les données personnelles, et privilégiez toujours les API officielles quand elles existent.


📚 Articles liés