Aller au contenu
AutoValue
17 octobre 2026 · Data Quality

La semaine où on a failli perdre 84 000 annonces à cause d'un bug qu'on a mis sur le dos des proxys

AutoValue Editorial
La semaine où on a failli perdre 84 000 annonces à cause d'un bug qu'on a mis sur le dos des proxys

14 septembre

On attendait ce jour depuis des semaines. Notre fournisseur de proxys résidentiels s'était volatilisé après un incident de facturation en juillet, et pendant deux mois, une part croissante de nos 1 375 sources tournait en mode dégradé, voire plus du tout — des requêtes qui expiraient, des IP bloquées en pleine session, le genre d'hémorragie lente qui ne ressemble pas à une panne mais plutôt à un chiffre qui se rétrécit sans que personne ne s'en aperçoive, jusqu'à ce que ça devienne gênant. On a renouvelé l'abonnement. Nouveau pool, 20 000 lignes de sessions résidentielles rotatives, chaque sortie testée avant d'approcher la production. 100 % du test passé. AE, DE, JP — tout était en ligne, tout était propre.

On a donc lancé un crawl supervisé, le genre où quelqu'un surveille vraiment le tableau de bord plutôt que de faire confiance au cron. Je m'attendais à tout sauf à un désastre.

Ce qu'on a obtenu, c'est une base de données qui avait perdu 84 401 lignes en un seul passage, avec 102 sources en baisse de plus de 25 % par rapport à leur dernier instantané. Pire que les deux mois de pénurie de proxys qu'on venait de résoudre.

La mauvaise piste, en bref

Mon premier réflexe — et je l'assume sans détour — a été de penser que le nouveau pool était en fait pire que ce que suggérait le test. Peut-être que les IP de session se retrouvaient limitées en plein crawl d'une façon qu'un test ponctuel ne pouvait pas détecter. C'est une théorie raisonnable. C'est aussi une théorie fausse, et y croire même une demi-journée nous a coûté du temps qu'on n'avait pas, parce que le cron de crawl reste en pause tout le temps qu'on débat une théorie de ce genre — on ne veut pas qu'un mauvais passage écrase un bon instantané pendant qu'on est encore en train de deviner.

L'indice qui a fait tomber cette théorie, c'est dubizzle. Une de nos sources les plus volumineuses pour les Émirats arabes unis : elle avait bel et bien récupéré 32 595 annonces pendant ce passage — un chiffre parfaitement sain, les proxys fonctionnaient clairement — puis avait jeté presque tout. Pas un échec de récupération. Une récupération réussie, suivie d'un rejet.

16 septembre : trouver le vrai bug

C'est là que l'histoire a cessé d'être une histoire de proxys pour devenir une histoire de remplacement de lignes. Notre couche de persistance prend un instantané de chaque source en écrasant intégralement <site>_cars_for_sale.csv à chaque passage — seulement les annonces en cours, on remplace toute la table. C'est le comportement correct quand un crawl se termine. C'est catastrophique quand un crawl expire en cours de route et que le scraper écrit le lot partiel qu'il a réussi à collecter comme s'il s'agissait de l'instantané complet. Une source qui héberge normalement 9 000 annonces actives se retrouve écrasée par les 1 200 qu'elle a réussi à scraper avant la fin du temps imparti, et les 7 800 autres disparaissent — non pas parce que les voitures ont été vendues, mais parce que notre propre code a décidé qu'une récupération incomplète était une récupération complète.

Les proxys ne nous mentaient pas. Le problème venait de la logique de nouvelles tentatives, et elle était discrètement défaillante depuis longtemps, simplement masquée par un pool plus performant qui avait l'habitude de terminer les récupérations avant que le balayage ne devienne un problème.

Voici ce que ce balayage a réellement coûté, une fois le calcul fait :

Ancien balayage de tentativesBalayage corrigé
Tentatives par proxy31
Délai par tentative1 s—
Plafond effectif sur un pool de 50 proxys~56 minutes par URLbudget total de 120 secondes
Comportement en cas d'expirationécrit le lot partiel comme instantané completsource ignorée, instantané précédent conservé

Cinquante-six minutes pour abandonner une seule URL. Multipliez ça sur un crawl touchant plus d'un millier de sources, et vous obtenez exactement le genre d'échec silencieux et inégalement répatti qu'on a observé — certaines sources parfaitement saines, 102 d'entre elles vidées, rien dans les journaux pour crier « panne de proxy », parce que, techniquement, il n'y en avait pas.

25 septembre : le correctif, et la partie qui vous concerne

Le correctif déployé neuf jours plus tard a fait deux choses peu spectaculaires. Il a plafonné le calcul des tentatives pour qu'une récupération bloquée échoue rapidement plutôt que de monopoliser presque une heure, et — voici celle qui empêche réellement la perte de données — une récupération partielle ne remplace plus l'ensemble complet des lignes. Si une source ne récupère que 1 200 de ses 9 000 annonces habituelles, on conserve l'instantané complet précédent au lieu de l'écraser par une fraction de celui-ci. Le même jour, un second changement est arrivé, qui écrit un indicateur CRAWL_PAUSED visible que notre supervision vérifie avant d'alerter qui que ce soit sur une baisse — pour qu'une pause volontaire soit lue comme une pause, et non comme une alerte.

Pourquoi un lecteur à la recherche d'une Hyundai d'occasion devrait-il s'intéresser à tout ça ? Parce que les signalements de prix sous le marché que nous publions — 12 823 en ligne sur le site à l'heure où nous écrivons — ne sont honnêtes que si la cohorte à laquelle on compare une annonce représente le marché régional réel et complet, et non un fragment tronqué par une expiration. Un badge « bonne affaire » construit sur un instantané qui a perdu les trois quarts de son ensemble de comparaison n'est pas un badge de bonne affaire, c'est du bruit déguisé en étiquette verte. On préfère mettre un crawl en pause pendant neuf jours plutôt que de publier ça.

Le jeu de données se situe aujourd'hui à 1 108 535 annonces répatties sur 73 régions et 1 375 sources — plus important qu'avant tout cet épisode, proxys renouvelés et bug de remplacement de lignes corrigé. Mais le chiffre vers lequel je reviens sans cesse, ce n'est pas le total. C'est 84 401 — l'écart entre un crawl qui semblait sain au niveau des proxys et un crawl qui l'était vraiment.

Data QualityWEB ScrapingCrawl ReliabilityBelow Market Deals
Partager

Articles similaires