← Retour au blog

Analyse d'images pour les ensembles de données CV : combien de trafic est nécessaire et quels proxies choisir

Nous analysons combien de trafic est réellement nécessaire pour collecter des milliers d'images pour former des modèles de CV, quels proxies utiliser et comment écrire un parser qui ne soit pas bloqué.

📅1 novembre 2026

La collecte de milliers d'images pour entraîner un modèle de vision par ordinateur est une tâche qui se heurte presque toujours à deux problèmes : les blocages de la part de la source de données (Google Images, Pinterest, places de marché, sites de stock) et une consommation de trafic étonnamment élevée. Une seule IP se fait rapidement bloquer, et la facture pour le trafic proxy peut dépasser le coût même de l'annotation de l'ensemble de données. Dans cet article, nous allons examiner comment concevoir un parseur d'images qui ne perd pas de données à cause des blocages, et comment calculer à l'avance le budget pour le trafic.

Pourquoi utiliser des proxies lors de la collecte d'images pour CV

Les ensembles de données pour la vision par ordinateur sont rarement collectés à partir d'une seule source. Il s'agit généralement d'une combinaison de résultats de recherche d'images, de fiches produits sur des places de marché, de banques d'images, de réseaux sociaux et d'API ouvertes. Presque toutes ces sources imposent des restrictions sur le nombre de requêtes à partir d'une seule IP : Google Images affiche un captcha après seulement quelques centaines de requêtes consécutives, Pinterest bloque temporairement l'accès à l'API, et Wildberries et Ozon renvoient des fiches vides ou redirigent vers une page de vérification en cas d'activité suspecte.

Sans proxies, vous atteignez un plafond de quelques centaines ou milliers d'images par jour à partir d'une seule adresse. Si vous avez besoin d'un ensemble de données de 50 000 à 500 000 images (c'est généralement le nombre requis pour les réseaux de neurones convolutifs et les transformateurs dans des tâches de classification et de détection), il est physiquement impossible de le collecter dans un délai raisonnable sans un pool distribué d'adresses IP — vous serez soit constamment confronté à des blocages, soit vous obtiendrez un échantillon fortement biaisé en raison des restrictions de temps et de géolocalisation.

La deuxième raison est la diversité géographique des données. Si le modèle doit reconnaître des objets de manière égale, peu importe la région de prise de vue (par exemple, les panneaux de signalisation dans différents pays ou les produits sur des places de marché locales), le parseur doit se connecter avec des IP de différents pays. Un seul centre de données avec une seule IP sortante ne pourra pas fournir cette diversité.

Combien de trafic est réellement nécessaire pour un ensemble de données

La consommation de trafic lors de la collecte d'images est souvent sous-estimée. Il ne s'agit pas seulement du poids des images elles-mêmes — les pages HTML, les bundles JS, les aperçus, les pixels de suivi et le CSS passent également par le proxy si le parseur n'est pas configuré précisément pour les URL nécessaires.

Type de contenu Poids moyen Trafic pour 10 000 unités
Aperçu/thumbnail (150–300 px) 15–40 Ko ~250 Mo
Photo de résolution moyenne (800–1200 px) 80–200 Ko ~1,4 Go
Photo de haute résolution (2000+ px) 400 Ko – 1,5 Mo ~9,5 Go
Page HTML de la fiche produit (sans images) 150–400 Ko ~2,7 Go

En pratique, si vous collectez 100 000 images de résolution moyenne avec les pages de fiches produits (pour extraire les annotations — catégories, boîtes, attributs), la consommation totale de trafic se situe généralement entre 25 et 45 Go. Si vous avez besoin d'images de haute résolution pour des tâches de détection d'objets petits — comptez sur 80 à 150 Go pour les mêmes 100 000 unités. Ces chiffres doivent être pris en compte lors du choix d'un tarif proxy à l'avance, et non après coup.

Datacenter, résidentiel et mobile : que choisir

Pour la collecte d'images, trois paramètres sont importants : la vitesse, le coût du trafic et la résistance aux blocages. Ces paramètres varient considérablement selon les types de proxies.

Paramètre Datacenter Résidentiel Mobile
Vitesse Élevée Moyenne Basse-moyenne
Résistance aux blocages Faible Élevée Très élevée
Coût du trafic Faible Moyenne-élevée Élevée
Convient pour API ouvertes, stocks sans protection stricte Google Images, Pinterest, places de marché Réseaux sociaux avec une protection anti-bot stricte

Pour la plupart des tâches de collecte d'images, un bon équilibre est fourni par les proxies résidentiels — les IP apparaissent comme des utilisateurs ordinaires, donc les systèmes anti-bot des places de marché et des moteurs de recherche d'images déclenchent moins souvent un captcha. Si la source est une banque d'images ouverte ou une API sans limites strictes, il est moins cher d'utiliser des proxies de datacenter — ils sont plus rapides et permettent de transférer de grands volumes de trafic à un coût par Go inférieur. Pour la collecte d'images à partir d'applications mobiles ou de réseaux sociaux avec une protection anti-bot avancée, les proxies mobiles sont plus adaptés — ils utilisent de véritables IP d'opérateurs de télécommunications et ne sont presque jamais bloqués.

Parseur de base avec requests et rotation de proxies

Pour commencer, un simple script synchrone avec requests et rotation de proxies pour chaque requête ou après un certain nombre de requêtes suffira. Voici un exemple de téléchargement d'images à partir d'une liste d'URL avec vérification du type de contenu et limitation de la taille du fichier, afin de ne pas télécharger accidentellement un fichier lourd dans un format incorrect.

import requests
import itertools
import hashlib
import os

PROXIES = [
    "http://user:[email protected]:10000",
    "http://user:[email protected]:10000",
    "http://user:[email protected]:10000",
]
proxy_cycle = itertools.cycle(PROXIES)

HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept": "image/avif,image/webp,image/*,*/*;q=0.8",
}

def download_image(url, save_dir="dataset", max_size_mb=10, timeout=15):
    proxy = next(proxy_cycle)
    proxies = {"http": proxy, "https": proxy}
    try:
        resp = requests.get(url, headers=HEADERS, proxies=proxies, timeout=timeout, stream=True)
        resp.raise_for_status()

        content_type = resp.headers.get("Content-Type", "")
        if "image" not in content_type:
            return None

        content_length = int(resp.headers.get("Content-Length", 0))
        if content_length > max_size_mb * 1024 * 1024:
            return None

        file_hash = hashlib.md5(url.encode()).hexdigest()
        ext = content_type.split("/")[-1].split(";")[0]
        filepath = os.path.join(save_dir, f"{file_hash}.{ext}")

        os.makedirs(save_dir, exist_ok=True)
        with open(filepath, "wb") as f:
            for chunk in resp.iter_content(chunk_size=8192):
                f.write(chunk)

        return filepath
    except requests.exceptions.RequestException as e:
        print(f"Erreur lors de {url} via {proxy}: {e}")
        return None

Le point clé est de vérifier Content-Length avant de télécharger le corps de la réponse. Cela économise du trafic en filtrant les fichiers trop lourds avant le téléchargement complet. La rotation des proxies via itertools.cycle répartit uniformément la charge entre les IP, réduisant le risque de blocage d'une adresse spécifique.

Collecte asynchrone avec aiohttp

Un script synchrone avec requests convient bien pour quelques milliers d'images, mais pour des ensembles de données de 50 000 fichiers et plus, l'asynchronicité est nécessaire — sinon, la collecte s'étendra sur des jours. aiohttp, associé à un sémaphore pour limiter le parallélisme, est une solution efficace pour des dizaines de milliers de tâches simultanées sans surcharger le pool de proxies.

import asyncio
import aiohttp
import itertools

PROXIES = [
    "http://user:[email protected]:10000",
    "http://user:[email protected]:10000",
]
proxy_cycle = itertools.cycle(PROXIES)
sem = asyncio.Semaphore(50)  # limitation des requêtes parallèles

async def fetch_image(session, url, idx):
    proxy = next(proxy_cycle)
    async with sem:
        try:
            async with session.get(url, proxy=proxy, timeout=15) as resp:
                if resp.status != 200:
                    return
                content_type = resp.headers.get("Content-Type", "")
                if "image" not in content_type:
                    return
                data = await resp.read()
                with open(f"dataset/{idx}.jpg", "wb") as f:
                    f.write(data)
        except Exception as e:
            print(f"Erreur {url}: {e}")

async def main(urls):
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_image(session, url, i) for i, url in enumerate(urls)]
        await asyncio.gather(*tasks)

# asyncio.run(main(url_list))

Un sémaphore de 50 connexions simultanées est un bon point de départ. Si les proxies résidentiels supportent la charge sans augmentation des erreurs 429 et des délais d'attente, vous pouvez progressivement augmenter jusqu'à 100-150. L'essentiel est de surveiller le pourcentage de requêtes échouées : s'il dépasse 5-7 %, il vaut mieux réduire le parallélisme plutôt que d'augmenter indéfiniment le pool de proxies.

Scrapy + middleware proxy pour une collecte à grande échelle

Pour la collecte en production d'ensembles de données avec une file d'attente intégrée, des retries et de la dé-duplication d'URL, il est plus pratique d'utiliser Scrapy avec ImagesPipeline. Elle télécharge elle-même les images, vérifie leur validité via PIL et peut générer des aperçus de différentes tailles.

# settings.py
ITEM_PIPELINES = {
    'scrapy.pipelines.images.ImagesPipeline': 1,
}
IMAGES_STORE = 'dataset_images'
IMAGES_MIN_HEIGHT = 200
IMAGES_MIN_WIDTH = 200

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.ProxyRotationMiddleware': 350,
}

CONCURRENT_REQUESTS = 32
DOWNLOAD_DELAY = 0.5
RETRY_TIMES = 3
# middlewares.py
import random

class ProxyRotationMiddleware:
    PROXIES = [
        "http://user:[email protected]:10000",
        "http://user:[email protected]:10000",
        "http://user:[email protected]:10000",
    ]

    def process_request(self, request, spider):
        request.meta['proxy'] = random.choice(self.PROXIES)

Les paramètres IMAGES_MIN_HEIGHT et IMAGES_MIN_WIDTH éliminent automatiquement les petites icônes et les sprites qui polluent l'ensemble de données et gaspillent du trafic. DOWNLOAD_DELAY de 0,5 seconde réduit la fréquence des requêtes à partir d'un seul proxy, ce qui diminue la part de captchas sur les sources avec un suivi anti-fraude strict comme Pinterest.

Comment réduire la consommation de trafic

Le trafic via des proxies est généralement facturé en fonction du volume, donc toute optimisation permet d'économiser directement le budget. Voici quelques astuces efficaces :

  • Demandez des aperçus, pas des originaux, si une résolution de 512–1024 px suffit pour l'entraînement — la plupart des sources fournissent l'image de la taille requise via une URL distincte ou un paramètre de requête.
  • Filtrez par Content-Length avant de télécharger le corps — une requête HEAD ou la lecture des en-têtes d'un GET en streaming permet d'éliminer les fichiers trop lourds sans gaspiller de trafic pour leur téléchargement.
  • Désactivez le téléchargement des ressources associées, si le parseur fonctionne via un navigateur sans tête : bloquez le CSS, les polices et les scripts de suivi, en ne laissant que le HTML et les images nécessaires.
  • Dédupliquez les URL avant la requête, et non après le téléchargement — les images identiques sur différentes pages de fiches produits (par exemple, sur Wildberries) ne doivent pas être téléchargées à nouveau.
  • Utilisez un cache local des réponses lors des exécutions répétées du parseur pendant le débogage, afin de ne pas faire passer le trafic via des proxies pour chaque exécution de test du code.

Erreurs fréquentes, 403 et limite de taux

Lors de la collecte d'images en grande quantité, le parseur sera inévitablement confronté à des réponses 403, 429 et des redirections temporaires vers des pages de vérification. Un traitement correct de ces codes permet d'économiser à la fois du trafic et le pool de proxies.

Code/symptôme Cause Que faire
403 Interdit IP sur liste noire de la source Rotation des proxies, changement de User-Agent
429 Trop de requêtes Limite de requêtes par minute dépassée Augmenter DOWNLOAD_DELAY, réduire le parallélisme
Redirection vers un captcha Analyse comportementale suspecte de bot Passer à des IP résidentielles/mobiles
Content-Length vide Réponse chunked ou placeholder au lieu de l'image Vérifier la taille réelle des octets téléchargés

Il est également important de journaliser le pourcentage de requêtes réussies pour chaque proxy. Si une IP spécifique donne systématiquement un 403 plus souvent que les autres — retirez-la automatiquement de la rotation, sans attendre qu'elle tire vers le bas la statistique globale de blocage pour tout le pool.

Calcul du budget pour le trafic proxy

Avant de commencer la collecte, il est utile d'estimer le volume de trafic à l'avance, plutôt que de le calculer a posteriori. La formule est simple : nombre d'images × poids moyen du fichier × coefficient de frais généraux (HTML, en-têtes, requêtes répétées à cause d'erreurs — généralement 1.3–1.6).

Exemple de calcul pour un ensemble de données de 200 000 images de résolution moyenne (~150 Ko) avec parsing des fiches produits : 200 000 × 150 Ko = 30 Go de poids net des images. En tenant compte des pages HTML et des requêtes répétées à cause de blocages temporaires (coefficient 1.5), la consommation totale est d'environ 45 Go. Si certaines sources nécessitent des IP mobiles en raison de la protection anti-bot, prévoyez cela dans le pool de proxies séparément, car le trafic sur des IP mobiles coûte généralement plus cher que sur des IP résidentielles ou de datacenter.

Une bonne pratique consiste à collecter un lot pilote de 1 000 à 2 000 images, à mesurer la consommation réelle de trafic et le pourcentage d'erreurs, puis à extrapoler sur l'ensemble du volume prévu de l'ensemble de données. Cela est plus précis que n'importe quel calcul théorique, car cela prend en compte la spécificité de la source particulière.

Conclusion

La collecte d'images pour entraîner des modèles de vision par ordinateur est une tâche à l'intersection de l'ingénierie des données et de la gestion efficace de l'infrastructure réseau. Une architecture de parseur correcte (asynchronicité, filtrage par Content-Length, dé-duplication des URL) économise du trafic, tandis qu'un choix réfléchi de proxies détermine si vous collecterez le volume nécessaire de l'ensemble de données en quelques jours ou en semaines de blocages constants.

Si les sources de données utilisent une protection anti-bot avancée — moteurs de recherche d'images, places de marché, réseaux sociaux — commencez par des proxies résidentiels : ils offrent le meilleur équilibre entre résistance aux blocages et coût du trafic. Pour les API ouvertes et les banques d'images sans limites strictes, il est judicieux d'économiser sur les proxies de datacenter, et pour les applications mobiles les plus protégées — de connecter des proxies mobiles pour la partie finale, la plus complexe de la collecte.