Lorsque vous scrapez quelques centaines de pages, une boucle synchrone convient parfaitement : vous envoyez une requête, attendez le HTML, le parsez, puis recommencez. Ce modèle s'effondre dès que vous avez besoin de milliers ou de millions de pages, car chaque requête bloque votre code pendant qu'un navigateur distant rend la page et qu'un proxy effectue ses tentatives. Le Crawlbase Crawler existe précisément pour supprimer cette attente. Vous lui transmettez des URL, il les met en file d'attente et les crawle en arrière-plan, puis livre chaque résultat terminé à un webhook que vous contrôlez.

Ce tutoriel vous montre comment utiliser le Crawler de bout en bout en Python : mettre en place un endpoint webhook qui reçoit les résultats, créer un Crawler pointant vers cet endpoint, pousser un lot d'URL via la Crawling API, et lire le HTML crawlé au fur et à mesure de son arrivée. Vous découvrirez en chemin les fonctionnalités qui rendent le Crawler adapté à la grande échelle : traitement asynchrone, requêtes normales ou JavaScript, facturation uniquement pour les requêtes réussies, et relances automatiques. Les exemples ciblent des pages publiques neutres, et une courte note sur le scraping responsable est proposée en fin d'article.

Ce que vous allez construire

Un pipeline asynchrone petit mais complet. D'un côté, un serveur webhook qui accepte les callbacks POST du Crawler et stocke chaque résultat. De l'autre, un script de push qui soumet des URL à votre Crawler nommé via la Crawling API. Les éléments que vous obtiendrez :

  • Récepteur webhook. Un endpoint Flask qui accepte le callback POST du Crawler, décompresse le corps gzip et sauvegarde le HTML crawlé sur disque.
  • Définition du Crawler. Un Crawler nommé dans votre dashboard, soit un Crawler normal (TCP) pour les pages statiques, soit un Crawler JavaScript pour les pages rendues côté client, pointant vers votre URL webhook.
  • Script de push. Un script Python qui envoie une liste d'URL au Crawler avec callback=true et crawler=YourCrawlerName, et affiche le request id (RID) retourné pour chacune.
  • Gestion des résultats. Les champs qui arrivent à chaque callback, notamment le RID, l'URL d'origine, les codes de statut et le corps de la page.

En quoi le Crawler asynchrone diffère d'une requête directe

Un appel direct à la Crawling API est synchrone : vous appelez api.get(url), votre code se bloque jusqu'à ce que la page soit récupérée et rendue, puis vous obtenez le HTML dans la même réponse. C'est le bon outil pour un petit nombre de pages ou pour un travail interactif où vous voulez le résultat immédiatement.

Le Crawler inverse ce flux. Vous poussez une URL, récupérez aussitôt un court request id, et continuez à pousser le reste de votre lot. Le Crawler crawle chaque page en arrière-plan, gérant le rendu, la rotation d'IP et les relances selon son propre calendrier, puis poste le résultat terminé à votre webhook quand il est prêt. Votre code ne maintient jamais une connexion ouverte pendant toute la durée d'un crawl. Ce découplage est ce qui permet à un lot de s'étendre sur des milliers d'URL sans que votre processus reste inactif, et c'est pourquoi la page produit async le recommande pour les gros travaux. La contrepartie : vous avez besoin d'un endpoint publiquement accessible pour recevoir les callbacks, ce que vous construisez en premier.

Deux types de Crawler

Lorsque vous créez un Crawler, vous choisissez un type. Un Crawler normal (TCP) récupère du HTML statique et constitue l'option la moins coûteuse pour les pages rendues côté serveur. Un Crawler JavaScript rend d'abord la page dans un vrai navigateur, ce dont vous avez besoin lorsque le contenu est construit côté client (React, Angular, ou tout ce qui se remplit après le chargement). Choisissez le type qui correspond à votre cible ; les requêtes JavaScript consomment plus de crédits que les requêtes normales.

Prérequis

Quelques éléments à mettre en place. Aucun ne prend longtemps.

Python basique. Vous devez être à l'aise pour exécuter un script et installer des packages avec pip. Si vous êtes novice en matière de traitement du HTML une fois arrivé, le guide BeautifulSoup se marie bien avec celui-ci.

Python 3.8 ou ultérieur. Confirmez avec python --version. Si vous ne l'avez pas, installez-le depuis python.org et assurez-vous qu'il figure dans votre PATH.

Un compte Crawlbase et un token. Inscrivez-vous, ouvrez votre dashboard et copiez votre token depuis la page de documentation du compte. Vous obtenez un token normal et un token JavaScript ; utilisez celui qui correspond au type de Crawler que vous créez. Crawlbase inclut 1 000 requêtes gratuites pour commencer, ce qui suffit pour suivre ce guide. Traitez le token comme un mot de passe et gardez-le hors du contrôle de version.

Un moyen d'exposer localhost. Le Crawler livre les résultats via l'internet public, donc votre webhook doit être accessible depuis l'extérieur de votre machine. Pour le développement local, un outil de tunnel comme ngrok redirige une URL publique vers votre port local. En production, vous hébergeriez l'endpoint sur un vrai serveur.

Mettre en place le projet

Créez un environnement virtuel pour que les dépendances restent isolées, puis installez les deux bibliothèques dont vous avez besoin : Flask pour le serveur webhook et le client officiel Crawlbase pour le script de push.

bash
python --version

python -m venv crawler_env
source crawler_env/bin/activate

pip install crawlbase flask

Sous Windows, activez l'environnement avec crawler_env\Scripts\activate à la place de la ligne source. Le package crawlbase est le client officiel pour pousser des URL via la Crawling API, et flask vous donne un serveur web minimal pour l'endpoint de callback. Le module gzip utilisé pour décompresser le corps du callback est livré avec la bibliothèque standard, donc il n'y a rien de plus à installer.

Étape 1 : Construire le récepteur webhook

Le Crawler livre chaque résultat sous forme de POST à votre URL de callback. Pour être un endpoint valide, votre webhook doit faire trois choses : être accessible depuis l'internet public, accepter les appels POST, et répondre rapidement avec un statut 200, 201 ou 204 et aucun corps. Le Crawler envoie le corps de la page compressé en gzip, donc vous le décompressez avant de le sauvegarder. Voici un récepteur Flask complet.

python
# webhook.py
import gzip
from flask import Flask, request, Response

app = Flask(__name__)

@app.route("/webhook/crawlbase", methods=["POST"])
def webhook():
    rid = request.headers.get("rid")
    url = request.headers.get("url")
    pc_status = request.headers.get("pc_status")

    try:
        body = gzip.decompress(request.data).decode("latin1")
    except OSError:
        body = request.data.decode("latin1", errors="replace")

    with open(f"result_{rid}.html", "w", encoding="latin1") as f:
        f.write(body)

    print(f"Received {rid} for {url} (status {pc_status})")
    return Response(status=204)

if __name__ == "__main__":
    app.run(port=8000)

L'endpoint lit le RID, l'URL crawlée et le statut Crawlbase depuis les en-têtes de la requête, décompresse le corps gzip en HTML, et l'écrit dans un fichier nommé d'après le RID, de sorte que chaque résultat arrive séparément. Il retourne 204 No Content, exactement ce que le Crawler attend : un acquittement rapide et vide. Exécutez-le avec python webhook.py et le serveur écoute sur le port 8000.

Maintenant, rendez-le public. Le serveur étant en cours d'exécution, démarrez un tunnel sur le même port :

bash
ngrok http 8000

ngrok affiche une URL de transfert publique telle que https://abc123.ngrok-free.app. Votre URL de callback complète est cet hôte plus la route, par exemple https://abc123.ngrok-free.app/webhook/crawlbase. Gardez-la à portée de main ; vous en aurez besoin à l'étape suivante. Avec le forfait gratuit de ngrok, l'URL change à chaque redémarrage, donc relisez-la après tout redémarrage.

Crawlbase Crawling API

Le webhook que vous venez de construire n'a qu'à recevoir du HTML terminé, car la partie difficile se passe en amont : lorsque le Crawler crawle chaque URL poussée, la Crawling API rend la page là où c'est nécessaire et fait tourner des IP résidentielles côté serveur, de sorte que vous ne gérez jamais vous-même une flotte de navigateurs headless ni un pool de proxies. Pointez un Crawler vers cet endpoint et poussez votre premier lot sur le forfait gratuit.

Étape 2 : Créer le Crawler

Avec une URL de callback publique en main, créez le Crawler depuis votre dashboard. Ouvrez la section Crawler et choisissez Créer un nouveau Crawler. Vous lui fournissez trois éléments :

  • Un nom. Un identifiant unique que vous référencerez lors du push d'URL, par exemple test-crawler.
  • Un type. Normal (TCP) pour les pages statiques ou JavaScript pour les pages rendues côté client, comme indiqué ci-dessus.
  • Une URL de callback. L'URL webhook publique de l'étape 1, y compris la route : https://abc123.ngrok-free.app/webhook/crawlbase.

Si vous préférez ne pas gérer votre propre endpoint, Crawlbase Cloud Storage peut servir de cible de callback et conserver les résultats pour que vous les récupériez plus tard. Pour ce tutoriel, nous utilisons le webhook que vous avez construit, car il montre le flux de callback complet. Une fois le Crawler sauvegardé, il est prêt à accepter des URL poussées.

Étape 3 : Pousser des URL vers le Crawler

Le push, c'est là qu'intervient la Crawling API. Vous l'appelez de la même façon que pour un crawl synchrone, mais vous ajoutez deux options : callback=true pour indiquer qu'il s'agit d'une requête asynchrone, et crawler=test-crawler pour nommer le Crawler qui doit la traiter. Chaque push retourne un request id plutôt que la page elle-même. Voici le script de push.

python
# push.py
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

urls = [
    "https://httpbin.org/html",
    "https://example.com/",
    "https://books.toscrape.com/",
]

OPTIONS = {"callback": "true", "crawler": "test-crawler"}

for url in urls:
    response = api.get(url, OPTIONS)
    print(response["body"])

Chaque appel retourne immédiatement avec un petit corps JSON contenant le RID, et le Crawler met l'URL en file d'attente pour un crawl en arrière-plan. Par défaut, vous pouvez pousser jusqu'à 30 URL par seconde ; si vous en avez besoin de plus, le support Crawlbase peut relever la limite. Notez qu'un token normal s'associe à un Crawler normal et un token JavaScript à un Crawler JavaScript, donc utilisez le token correspondant au type que vous avez créé.

Ce que le push retourne

Exécutez python push.py et vous obtenez un RID par URL, dans l'ordre où vous les avez poussées :

json
{"rid": "d756c32b0999b1c0507e364f"}
{"rid": "455ee207f6907fbd6168ac1e"}
{"rid": "e9eb6ce579dec207e8973615"}

Le RID est votre identifiant pour chaque requête. Vous pouvez l'utiliser pour rechercher une requête ultérieurement via les endpoints de gestion du Crawler, et il arrive sur le callback pour que vous puissiez faire correspondre chaque résultat à l'URL que vous avez poussée. Comme le push est asynchrone, le lot entier retourne en bien moins d'une seconde ; le crawl effectif se passe ensuite, en arrière-plan.

Étape 4 : Recevoir les résultats au webhook

Une fois qu'une page est crawlée, le Crawler poste le résultat par POST à votre URL de callback. Le corps est la page compressée en gzip, et les métadonnées voyagent dans les en-têtes. La réponse par défaut est du HTML, avec des en-têtes de cette forme :

json
Content-Type:     text/plain
Content-Encoding: gzip
Original-Status:  200
PC-Status:        200
rid:              the RID you received in the push call
url:              the URL which was crawled

Body: the gzip-compressed HTML of the page

Original-Status est le statut retourné par le site cible, et PC-Status est le statut propre à Crawlbase pour le crawl, ce qui vous permet de distinguer une récupération réussie d'une échouée et d'agir en conséquence. Si vous préférez une sortie structurée plutôt que du HTML brut, passez format=json lors du push, et le corps arrive sous forme d'objet JSON à la place :

json
{
  "pc_status": 200,
  "original_status": 200,
  "rid": "the RID you received in the push call",
  "url": "the URL which was crawled",
  "body": "the HTML of the page"
}

Comme nous avons poussé trois URL, le webhook reçoit trois POST, chacun écrivant son propre fichier result_<rid>.html. Avec le HTML sur disque, vous pouvez le parser comme vous le souhaitez ; c'est le moment où vous le chargeriez dans BeautifulSoup et extrairiez les champs qui vous intéressent, exactement comme après un crawl synchrone.

En-têtes de callback personnalisés

Si vous devez transmettre vos propres identifiants jusqu'au callback, passez un paramètre callback_headers lors du push, formaté comme NAME:VALUE|NAME2:VALUE2 (encodé en URL). Le Crawler renvoie ces en-têtes sur le résultat, ce qui vous permet d'attacher un identifiant de job ou une clé d'enregistrement à chaque URL et de le lire depuis le callback sans recherche séparée.

Fonctionnalités clés qui comptent à grande échelle

Le flux en quatre étapes ci-dessus constitue l'ensemble du schéma. Ce qui lui permet de tenir sur des millions d'URL, c'est un ensemble de comportements du Crawler qu'il vaut la peine de souligner.

  • Traitement asynchrone. Le push retourne un RID instantanément et le crawl s'effectue en arrière-plan, de sorte que votre code n'est jamais bloqué à attendre une page lente. Un seul processus peut pousser un très grand lot et recevoir simplement les résultats au fur et à mesure de leur arrivée.
  • Requêtes normales versus JavaScript. Un Crawler normal récupère du HTML statique à moindre coût ; un Crawler JavaScript rend la page dans un navigateur pour le contenu côté client. Vous choisissez par Crawler, et les requêtes JavaScript consomment plus de crédits que les requêtes normales, donc vous ne payez le rendu que lorsque vous en avez besoin.
  • Paiement par requête réussie. Vous êtes facturé pour les requêtes qui réussissent, pas pour chaque tentative, ce qui maintient le coût d'un grand crawl lié aux résultats plutôt qu'aux efforts.
  • Relances automatiques. Si le Crawler livre à votre webhook mais que votre serveur ne retourne pas un statut de succès, il relance le crawl et relivrera. Ces relances comptent bien comme des requêtes réussies une fois qu'elles arrivent, donc gardez votre endpoint rapide et retournant 204.

Un détail opérationnel : si votre webhook se déconnecte, le monitoring de Crawlbase le détecte et met le Crawler en pause, puis reprend une fois que l'endpoint est accessible. Les files d'attente combinées de vos Crawlers sont plafonnées ; un push se met en pause avec une notification par email si vous atteignez le plafond et reprend à mesure que la file se vide. Vous touchez rarement tout cela directement, mais c'est pourquoi un job asynchrone de longue durée ne perd pas silencieusement des résultats.

Mise à l'échelle du pipeline

Pour une exécution en production, la forme reste la même ; vous changez les entrées et le côté récepteur. Quelques bonnes pratiques permettent de garder les grands jobs en bonne santé :

  • Groupez vos pushs. Lisez les URL depuis un fichier ou une file et poussez-les en boucle, en restant dans la limite de 30 par seconde par défaut sauf si vous avez demandé une limite plus élevée. Stockez chaque RID retourné pour pouvoir réconcilier les résultats plus tard.
  • Rendez le webhook durable. Acquittez rapidement avec un 204, puis traitez le corps hors bande (écrivez en stockage ou transmettez à une file de workers) plutôt que de parser dans la requête. Un webhook lent déclenche des relances que vous payez.
  • Surveillez les codes de statut. Suivez PC-Status et Original-Status sur chaque callback pour distinguer les vraies erreurs de pages des erreurs transitoires, et réinjectez dans la file celles qui le nécessitent.

Si vous préférez ne pas gérer du tout le stockage des callbacks, pointez le Crawler vers Crawlbase Cloud Storage et récupérez les résultats à votre propre rythme. Pour un traitement plus complet de la mise en place d'un service de callback et de la persistance des résultats, voir l'extraction de données avec le Crawlbase Crawler et le guide pour construire un pipeline de données web scalable. Si vos cibles sont fortement rendues côté client, le guide crawler des sites web JavaScript couvre le côté rendu plus en profondeur.

Scraping responsable

Le Crawler rend la collecte à grande échelle simple, ce qui fait de l'utilisation responsable une question de discipline plutôt que de capacité. Scrapez uniquement des données publiques, les pages auxquelles tout le monde peut accéder sans compte, et restez à l'écart de tout ce qui se trouve derrière une connexion ou un paywall. Vérifiez les conditions d'utilisation de chaque site cible et son robots.txt, et traitez les deux comme la limite de ce que vous collectez.

Gardez votre taux de requêtes raisonnable. Le modèle asynchrone peut pousser fort, donc fixez des volumes qui ne sollicitent pas excessivement les sites que vous crawlez. Lorsque les données que vous collectez incluent quoi que ce soit lié à des personnes identifiables, traitez-les comme des données personnelles et gérez-les conformément aux réglementations telles que le RGPD et le CCPA : minimisez ce que vous conservez, agrégez lorsque vous le pouvez, et ne construisez pas de profils de personnes. Les exemples d'URL neutres dans ce guide (httpbin, example.com et une librairie sandbox) existent précisément pour que vous puissiez tester le flux sans le pointer vers un site de production réel.

Récapitulatif

Points clés

  • Le Crawler est asynchrone par conception. Vous poussez des URL, récupérez instantanément un RID, et recevez les résultats terminés à un webhook, de sorte que votre code ne se bloque jamais sur un crawl lent.
  • Vous construisez deux côtés. Un endpoint webhook public qui accepte les callbacks POST et retourne 204, et un script de push qui soumet des URL via la Crawling API avec callback=true et crawler=YourCrawlerName.
  • Choisissez le type de Crawler selon la cible. Un Crawler normal (TCP) pour les pages statiques, un Crawler JavaScript pour les pages rendues côté client ; les requêtes JavaScript coûtent plus de crédits, donc vous ne payez le rendu que lorsque c'est nécessaire.
  • Les livraisons échouées sont automatiquement relancées. Si votre webhook n'acquitte pas avec un statut de succès, le Crawler relivrera, et ces relances comptent comme des requêtes réussies, donc gardez l'endpoint rapide.
  • Restez sur les données publiques. Respectez les CGU et le robots.txt de chaque site, gardez votre taux raisonnable, et gérez toute donnée personnelle conformément au RGPD et au CCPA.

Foire aux questions

En quoi le Crawler diffère-t-il d'un appel normal à la Crawling API ?

Un appel normal à la Crawling API est synchrone : vous attendez la réponse et obtenez le HTML dans la même requête. Le Crawler est asynchrone : vous poussez une URL, obtenez immédiatement un request id, et le résultat terminé est posté à votre webhook ultérieurement. Utilisez un appel direct pour quelques pages ou un travail interactif, et le Crawler lorsque vous devez traiter des milliers ou des millions d'URL sans bloquer votre code.

Que doit faire mon webhook pour être valide ?

Il doit être accessible depuis l'internet public, accepter les requêtes POST et répondre rapidement avec un statut 200, 201 ou 204 et aucun corps. Le Crawler envoie la page compressée en gzip, donc décompressez le corps avant de l'utiliser. Acquittez rapidement et faites le traitement plus lourd ensuite, car un webhook lent peut déclencher des relances.

Dois-je utiliser Python ?

Non. Python est pratique ici grâce au client Crawlbase officiel et à Flask, mais le Crawler est agnostique au langage. Le côté push est un appel à la Crawling API avec callback=true et crawler=YourCrawlerName, et le webhook est n'importe quel endpoint HTTP qui accepte un POST. Vous pouvez construire les deux côtés en JavaScript, Ruby, Go, ou tout ce qui parle HTTP.

Qu'est-ce que le RID et comment l'utiliser ?

Le RID (request id) est retourné lorsque vous poussez une URL et renvoyé sur le callback. Il vous permet de faire correspondre chaque résultat entrant à l'URL que vous avez soumise, et vous pouvez l'utiliser pour rechercher une requête via les endpoints de gestion du Crawler. Stocker le RID pour chaque push est le moyen le plus simple de réconcilier un grand lot au fur et à mesure que les résultats arrivent.

Quand dois-je utiliser un Crawler JavaScript plutôt qu'un Crawler normal ?

Utilisez un Crawler JavaScript lorsque le contenu dont vous avez besoin est rendu côté client, par exemple une application React ou Angular, ou une page qui se remplit après le chargement. Un Crawler normal (TCP) suffit pour le HTML statique rendu côté serveur et coûte moins de crédits par requête. Faites correspondre le type de Crawler à votre cible, et utilisez le token (normal ou JavaScript) qui lui correspond.

Comment fonctionne la facturation avec les relances ?

Vous ne payez que pour les requêtes réussies plutôt que pour chaque tentative, et les requêtes JavaScript consomment plus de crédits que les requêtes normales. Si le Crawler tente de livrer un résultat mais que votre webhook ne retourne pas un statut de succès, il relance et relivrera ; ces relances comptent comme des requêtes réussies une fois qu'elles arrivent. Garder votre endpoint rapide et retournant 204 évite de payer pour des relances évitables.

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