Un site ne passe presque jamais d’un état où il sert normalement votre crawler à un blocage pur et simple en une seule étape. Ce qui se passe d’abord est plus discret. Quelques requêtes supplémentaires tombent sur une page de challenge. Certaines réponses reviennent en 200 OK sans rien d’utile à l’intérieur. La latence grimpe petit à petit. Une poignée d’enregistrements échouent à la validation. Chaque signal pris isolément ressemble à du bruit, et chacun vit sur un tableau de bord différent, si bien que personne ne fait le lien avant que le dataset ne présente un trou.
Un score de santé de cible est la solution : un nombre unique par site qui indique si ce site se comporte encore comme à son habitude, avec les raisons attachées. Cet article couvre quels signaux l’alimentent, comment les combiner sans se leurrer soi-même, et ce que le crawler doit faire quand ce nombre chute.
La santé de la cible n’est pas la santé du proxy
Il vaut la peine d’être précis sur ce qui est mesuré, car les deux notions sont souvent confondues.
La santé du proxy demande si une route fonctionne : une gateway, un pays, une session, une sortie. La santé de la cible demande si un site précis est encore disposé et capable de vous servir. Une route de proxy morte échoue contre tous les sites. Un site qui se retourne contre vous échoue sur toutes les routes.
Cette différence est le premier diagnostic. Quand les échecs augmentent, répartissez-les par route. S’ils se concentrent sur un pays, un pool ou un schéma de session, il s’agit d’un problème de route, et l’approche décrite dans monitoring residential proxy health at scale s’applique. S’ils augmentent uniformément sur toutes les routes que vous envoyez vers ce site, c’est le site qui a changé d’avis à votre sujet, et c’est précisément à cela que sert ce score.
Les signaux
Regroupez les signaux selon ce qu’ils révèlent. Certains sont bruyants, d’autres presque silencieux, et les silencieux sont les plus coûteux à manquer.
| Signal | À quoi cela ressemble | Pourquoi c’est important |
|---|---|---|
| Blocages francs | 403, 429, réinitialisations de connexion | Refus explicite ; facile à comptabiliser |
| Challenges | Pages CAPTCHA ou interstitielles | Le site soupçonne de l’automatisation et teste |
| Blocages doux | 200 OK avec une page de blocage, des résultats vides ou une mise en page dépouillée | Refus déguisé en succès |
| Dérive de latence | Temps de réponse p95 en hausse par rapport à la normale propre au site | Souvent un ralentissement délibéré, parfois simplement de la charge |
| Échecs d’extraction | Champs requis manquants, schéma qui ne correspond plus | La page a changé, ou on vous sert autre chose |
| Dérive de coût | Plus de tentatives, d’octets ou de crédits par enregistrement valide | Tout ce qui précède, exprimé en argent |
Les blocages doux méritent une attention particulière car les codes de statut mentent. Dans une mesure de 2023 sur le geo-blocking depuis Cuba, 32 domaines servaient leurs pages de blocage avec un statut 200 OK, comme décrit dans which countries get geo-blocked most. Un crawler qui fait confiance au code de statut enregistre cela comme des succès. Détectez les blocages doux par le contenu : marqueurs connus de page de blocage, taille de réponse très en dessous de la normale pour ce type de page, ou une extraction qui ne renvoie rien là où elle renvoyait toujours quelque chose.
Deux propriétaires, deux scores
Une distinction évite beaucoup de confusion : séparer « le site a changé » de « le site s’est retourné contre vous ».
Une refonte casse votre parseur. Chaque page se charge correctement, mais les champs requis disparaissent. C’est un problème d’extraction avec une correction de code, dont le propriétaire est celui qui maintient le parseur. Un site qui commence à challenger et à bloquer doucement est un problème de relation, et la correction est un changement dans la façon, la quantité ou le fait même de collecter. Propriétaires différents, réponses différentes.
Calculez donc l’hostilité, c’est-à-dire les blocages, les challenges, les blocages doux et la latence, comme le score de santé, et suivez la validité de l’extraction séparément comme un signal distinct de santé du parseur. Quand les deux chutent en même temps, regardez d’abord l’hostilité : un site qui sert des pages de challenge cassera aussi tous les extracteurs.
Comparer par rapport à la normale propre au site
L’erreur la plus courante est d’utiliser des seuils globaux. Un taux de challenge de 5% est alarmant sur un site qui ne vous a jamais challengé, et parfaitement normal sur un site qui challenge tout le monde dès la première visite. Chaque signal doit être comparé à la normale propre à ce site, sur une fenêtre suffisamment longue pour être stable, comme les deux semaines précédentes, en excluant le jour le plus récent, afin qu’une mauvaise journée ne devienne pas la nouvelle normale.
Puis pondérez, plafonnez et sommez :
from dataclasses import dataclass
@dataclass
class Window:
requests: int
hard_blocks: int # 403, 429, connection resets
challenges: int # CAPTCHA or interstitial pages
soft_blocks: int # 200 OK carrying a block page or an empty result
p95_latency_ms: float
MIN_REQUESTS = 50
WEIGHTS = {"hard_block": 35, "challenge": 25, "soft_block": 25, "latency": 15}
def signals(w):
n = max(1, w.requests)
return {
"hard_block": w.hard_blocks / n,
"challenge": w.challenges / n,
"soft_block": w.soft_blocks / n,
"latency": w.p95_latency_ms,
}
def badness(name, now, base):
if name == "latency":
# Full penalty at three times the site's own normal latency.
return min(1.0, max(0.0, (now / max(base, 1.0) - 1) / 2))
# Full penalty at 20 percentage points above the site's own normal rate.
return min(1.0, max(0.0, (now - base) / 0.20))
def health_score(current, baseline):
if current.requests < MIN_REQUESTS:
return None, ["not enough requests to judge"]
now, base = signals(current), signals(baseline)
penalty = {k: w * badness(k, now[k], base[k]) for k, w in WEIGHTS.items()}
score = round(100 - sum(penalty.values()))
reasons = [k for k, p in sorted(penalty.items(), key=lambda kv: -kv[1]) if p >= 1]
return score, reasons
Plusieurs choix de conception ici sont délibérés.
- Seul l’excès par rapport à la baseline compte. Un site qui a toujours challengé 3% des requêtes ne perd aucun point pour cela aujourd’hui.
- Chaque signal est plafonné. Un signal qui s’emballe ne peut pas faire chuter le score sous zéro ni noyer les autres, et la liste des raisons montre lequel a dominé.
- Une petite fenêtre ne renvoie aucun score. Cinq requêtes avec un blocage n’est pas un taux de blocage de 20%, ce n’est simplement pas assez de données. L’absence de score est plus honnête qu’un score confiant mais faux.
- Les poids sont des opinions. Commencez avec quelque chose comme ceci, puis ajustez après avoir passé en revue quelques incidents réels. Les blocages francs et les blocages doux méritent le plus de poids car ils signifient des données que vous n’avez pas obtenues.
Lissez aussi le score dans le temps, par exemple avec une moyenne pondérée exponentielle, afin qu’une seule mauvaise minute ne déclenche pas une alerte intermittente, tandis qu’un déclin régulier reste visible dans l’heure.
Canaris : une vérité terrain que vous contrôlez
Chaque signal ci-dessus est inféré. Les canaris vous donnent quelque chose de plus proche de la vérité. Choisissez une poignée de pages stables par site où vous connaissez la bonne réponse : un produit dont vous pouvez vérifier le prix, une liste dont vous connaissez le nombre d’articles, une page dont la structure n’a pas changé depuis des mois. Récupérez-les selon un calendrier, via le même chemin que le trafic de production.
Quand un canari renvoie une page qui semble normale mais porte la mauvaise valeur, vous avez trouvé l’échec le plus difficile à détecter : un contenu qui se parse parfaitement et qui n’est simplement pas ce qu’un vrai visiteur verrait. Aucun code de statut ni graphique de latence ne vous montrera cela. Les canaris rendent aussi la baseline fiable, car vous connaissez leur comportement correct indépendamment du crawler.
Associer des actions aux plages, et garder des humains dans la boucle
Un score sur lequel personne n’agit n’est qu’un tableau de bord. Donnez-lui des plages, et donnez à chaque plage une action que le système prend de lui-même :
| Plage | Signification | Action automatique |
|---|---|---|
| 80 à 100 | Se comporte comme d’habitude | Aucune |
| 50 à 79 | En dégradation | Réduire la concurrence pour ce site, allonger les intervalles de revisite, vérifier si les échecs sont propres au site ou à la route |
| En dessous de 50 | Le site résiste clairement | Mettre le site en pause, ne conserver que les canaris en fonctionnement, alerter une personne |
La plage de dégradation alimente directement le reste du crawler. Réduire la concurrence, c’est précisément l’objet du limiteur par hôte décrit dans backpressure and flow control, et un score en baisse devrait augmenter le coût effectif de ce site dans un cost-aware scheduler, afin que le budget se déplace vers les sites où il achète encore des données.
La plage la plus basse n’est délibérément pas automatisée au-delà d’une mise en pause. Un site qui résiste fortement vous dit quelque chose, et la bonne réponse est une décision humaine : ralentir davantage, vérifier si votre collecte respecte encore les conditions du site, chercher une API officielle ou un flux de données, ou arrêter. Escalader automatiquement vers des méthodes de collecte plus lourdes chaque fois que le score baisse ne fait que transformer un signal en course aux armements, et c’est exactement ce qu’un score de santé devrait vous aider à éviter. Rate limiting and request throttling explique comment lire ce qu’un site vous demande.
Le passer en revue comme toute autre alerte
Traitez le score comme une alerte avec un taux de faux positifs, et passez-le en revue. Après chaque incident, demandez-vous si le score a bougé assez tôt, si les raisons pointaient vers la cause réelle, et si l’action automatique a aidé. La majeure partie de l’ajustement vient de deux ou trois incidents réels, pas de la conception des poids à l’avance. Conservez l’historique : le score sur plusieurs mois est le meilleur enregistrement dont vous disposiez de la manière dont l’attitude de chaque site envers le trafic automatisé évolue.
En résumé
Les sites se retournent contre les crawlers progressivement et discrètement, via des challenges, des refus déguisés et des réponses plus lentes, bien avant un blocage pur et simple. Chaque signal pris isolément est ambigu. Comparés à la normale propre au site, pondérés, plafonnés et combinés, ils donnent un nombre unique qui bouge tôt, avec des raisons attachées.
Le score est surtout précieux pour ce qu’il permet au crawler de faire calmement : ralentir avant d’être bloqué, déplacer le budget ailleurs, et remettre les décisions difficiles à une personne disposant des preuves sous les yeux. Les métriques plus larges qui l’entourent se trouvent dans monitoring a web scraping pipeline.