Scarnox · Blog

Scraper sans se faire bloquer : guide pratique avec du code

Se faire bloquer pendant le scraping signifie généralement l'une de trois choses : vous avez envoyé trop de requêtes trop vite, votre client ressemblait à tout sauf à un navigateur ou à un bot connu, ou votre adresse IP figure sur une liste à laquelle le site fait moins confiance. Vous pouvez réduire les trois avec quelques bonnes habitudes : repérer le blocage tôt, ralentir lorsque le site vous repousse, garder une identité cohérente et honnête, et n'utiliser les proxys que lorsqu'ils sont appropriés. Ce guide détaille chacune de ces habitudes avec du code fonctionnel. Utilisez-le pour les sites que vous avez le droit de scraper.

Reconnaître un blocage

Un blocage ne ressemble pas toujours à une page d'erreur. Surveillez :

Journalisez le code de statut et un court extrait du corps de la réponse pour chaque échec. Un blocage que vous ne voyez pas dans vos journaux est un blocage que vous ne pouvez pas corriger.

Reculer avec des nouvelles tentatives

Lorsque le site dit « ralentis », votre code doit ralentir de plus qu'un peu. Le recul exponentiel, avec une limite de tentatives, est l'approche standard. Il respecte aussi Retry-After lorsque le site l'envoie :

import time
import requests

session = requests.Session()
session.headers.update({
    "User-Agent": "ExampleBot/1.0 (+https://example.com/bot)",
    "Accept-Language": "en-US,en;q=0.9",
})

def polite_get(url: str, max_attempts: int = 4) -> requests.Response:
    delay = 2.0
    resp = None
    for _ in range(max_attempts):
        resp = session.get(url, timeout=30)
        if resp.status_code not in (429, 503):
            return resp
        retry_after = resp.headers.get("Retry-After", "")
        wait = float(retry_after) if retry_after.isdigit() else delay
        time.sleep(wait)
        delay *= 2
    return resp  # toujours bloqué : renvoyer la dernière réponse à l'appelant

resp = polite_get("https://example.com/products?page=1")
print(resp.status_code, len(resp.text))

Remarquez ce que la fonction ne fait pas. Elle ne réessaie pas une 403, et elle ne change pas d'identité pour contourner un blocage. Une 403 est une décision d'arrêt, et non une énigme à résoudre.

Diagnostiquer un blocage étape par étape

Lorsqu'une exécution commence à échouer, passez ces vérifications en revue avant de modifier autre chose :

  1. Regardez la première URL en échec et son code de statut. Un blocage commence généralement à un point précis, pas au hasard.
  2. Comparez le rythme des requêtes dans les minutes qui précèdent le premier échec. Une rafale est la cause la plus courante.
  3. Vérifiez si l'échec est lié à un seul chemin, à une seule section ou à une heure précise de la journée.
  4. Chargez la même URL une fois à la main dans un navigateur normal. Si le navigateur la charge, la différence vient de votre schéma de requêtes. Si le navigateur est bloqué aussi, le site ne sert plus la page pour le moment.
  5. Ce n'est qu'ensuite que vous modifiez le code. Ralentissez d'abord, ajoutez le recul ensuite, et revoyez votre identité en dernier.

Modifier plusieurs choses à la fois rend impossible de savoir laquelle a aidé.

Garder une identité cohérente et honnête

Les scrapers se font bloquer lorsque leur identité change entre les requêtes, ou lorsqu'elle ne correspond pas au reste du trafic. Une seule session avec un User-Agent clair et stable est l'identité la plus simple et la plus fiable. Donnez un nom à votre bot, ajoutez un lien de contact, et n'envoyez que les en-têtes qu'un client normal enverrait. Changer de User-Agent pour ressembler à de nombreux visiteurs différents est une forme d'évasion, et cela rend généralement le blocage plus probable, pas moins.

Si un site sert un contenu différent aux navigateurs et aux clients HTTP simples, utilisez un vrai navigateur pour ces pages et gardez la même limite de débit. C'est une voie légitime, et elle garde un schéma de requêtes cohérent.

Utiliser les proxys avec précaution

Un proxy change l'adresse d'où part une requête. C'est un outil pour des besoins légitimes, comme tester depuis une région précise sur un site que vous avez le droit de tester, ou répartir la charge sur votre propre infrastructure. Ce n'est pas un moyen d'échapper à une limite que le site vous a imposée. Le format d'un proxy est celui qu'utilisent les types de tâches proxy :

proxies = {
    "http": "http://user:pass@proxy.example.net:8000",
    "https": "http://user:pass@proxy.example.net:8000",
}
resp = session.get("https://example.com/products", proxies=proxies, timeout=30)

Le choix du type de proxy est une question distincte, traitée dans proxys résidentiels ou de datacenter et proxys rotatifs pour le scraping.

Lorsque le blocage devient un captcha

Certains sites répondent à un problème de débit par un captcha plutôt que par un blocage pur. L'ordre raisonnable est le suivant : s'arrêter, ralentir, revérifier les règles, et seulement ensuite envisager une résolution. Pour les widgets PopularCaptcha, l'API en production de Scarnox renvoie un jeton que vous soumettez dans le champ h-captcha-response. Pour les autres types de captcha, consultez la liste en vigueur, car reCAPTCHA, Cloudflare Turnstile, GeeTest, AWS WAF et Arkose arrivent bientôt. Le guide détaillé est captchas dans le web scraping.

Si vous commencez à voir des blocages sur un site, la cause est presque toujours le schéma de requêtes. Éviter les captchas lors du scraping présente les habitudes qui préviennent le problème.

Scraper de manière responsable

Prochaines étapes