Zalando est l'un des plus grands détaillants de mode en Europe, et ses pages produits publiques contiennent exactement les données structurées qui alimentent la surveillance des prix, le suivi des assortiments et la recherche sur les tendances de la mode : noms de produits, marques, prix, tailles disponibles et couleurs. Le problème est que Zalando rend ces pages avec JavaScript et se défend vigoureusement contre les bots, de sorte qu'une requête HTTP simple vous donne une coquille vide ou une page de défi au lieu du catalogue que vous cherchez.

Ce guide vous montre comment construire un scraper Zalando en Python de façon fiable. Vous récupérez des pages produits entièrement rendues via la Crawling API en utilisant son token JavaScript, analysez le balisage avec BeautifulSoup et extrayez les champs qui comptent. L'ensemble du tutoriel se limite aux données de produits publics, et la section sur la légalité vers la fin n'est pas du remplissage, lisez-la avant de pointer cet outil sur un volume réel.

Ce que vous allez construire

Un script Python qui prend l'URL publique d'un produit Zalando, récupère le HTML rendu via la Crawling API et extrait un enregistrement structuré de l'article. Nous utiliserons une seule page produit comme exemple fil rouge et extrairons ces champs :

  • Product name le titre de l'article, par exemple "Leather Handbag".
  • Brand la marque derrière le produit, comme "Zign".
  • Price le prix de vente actuel, devise incluse.
  • Available sizes les tailles affichées comme disponibles sur la page.
  • Color le coloris de la variante listée.

Une fois qu'une page fonctionne, nous parcourons une liste d'URLs produits en rythmant les requêtes afin qu'un travail réel reste en bonne santé. Le catalogue de mode est une cible classique du scraping web e-commerce, et le schéma présenté ici se transpose à la plupart des détaillants.

Pourquoi une simple requête échoue sur Zalando

Si vous interrogez une URL produit Zalando avec un client HTTP brut, vous obtenez l'une de deux réponses inutiles : un statut 200 avec presque aucune donnée produit dans le body, ou un défi bot. Deux facteurs jouent contre vous. Premièrement, Zalando rend son contenu produit dans le navigateur avec JavaScript, de sorte que le HTML initial est une coquille qui ne se remplit qu'après l'exécution des scripts de la page. Deuxièmement, Zalando signale le trafic automatisé rapidement : les IP de datacenter et les schémas de requêtes qui ne ressemblent pas à un vrai navigateur sont challengés ou bloqués avant d'atteindre le contenu rendu.

Un scraper Zalando fonctionnel a donc besoin de deux choses en une seule requête : un navigateur qui rend réellement la page, et une IP que la plateforme lit comme un vrai visiteur. Vous pouvez assembler cela vous-même avec un navigateur sans tête et un pool de proxies résidentiels tournants, mais assembler ces éléments et les maintenir en bonne santé représente la majorité du travail. La Crawling API regroupe les deux dans un seul appel : vous lui envoyez l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance et renvoie le HTML final à analyser. Si vous souhaitez comprendre pourquoi le rendu côté client casse les scrapers naïfs, consultez comment crawler des sites JavaScript.

Why the JS token

Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend la page dans un vrai navigateur d'abord. Zalando est rendu côté client, vous avez donc besoin du token JS ici. Utiliser le token normal renvoie la même coquille vide qu'une récupération simple, et il n'y a rien d'utile à en analyser.

Prérequis

Quelques éléments doivent être en place avant d'écrire du code. Aucun d'eux ne prend longtemps.

Basic Python. Vous devez savoir écrire et exécuter un script Python et installer des paquets avec pip. Si BeautifulSoup est nouveau pour vous, notre guide BeautifulSoup en Python couvre les bases d'analyse que ce tutoriel suppose acquises.

Python 3.8 or later. Confirmez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda.

A Crawlbase account and JS token. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token JavaScript (JS) depuis la page de documentation du compte. Traitez le token comme un mot de passe : il authentifie vos requêtes, gardez-le hors du contrôle de version.

Configurer le projet

Créez un environnement virtuel afin que les dépendances du projet restent isolées, puis installez les deux bibliothèques dont le scraper a besoin.

bash
python --version

python -m venv zalando_env
source zalando_env/bin/activate

pip install crawlbase beautifulsoup4

Sous Windows, activez l'environnement avec zalando_env\Scripts\activate à la place de la ligne source. Deux dépendances font le travail : crawlbase est le client officiel pour la Crawling API, et beautifulsoup4 analyse le HTML renvoyé afin que vous puissiez extraire les champs individuels par sélecteur CSS.

Étape 1 : Récupérer la page produit rendue

Commencez par récupérer la page finale. Importez la classe CrawlingAPI, initialisez-la avec votre token JS et demandez l'URL du produit. Vérifier le code de statut avant d'analyser permet de faire remonter les erreurs clairement plutôt que silencieusement.

python
from crawlbase import CrawlingAPI

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

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['status_code']}")
    return None

if __name__ == "__main__":
    page_url = "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html"
    html = crawl(page_url)
    print(html[:500] if html else "No HTML returned")

Les deux options d'attente comptent pour une cible rendue côté client comme celle-ci. ajax_wait indique à l'API d'attendre que le contenu asynchrone finisse de charger, et page_wait maintient pendant un nombre fixe de millisecondes après le chargement afin que les éléments à rendu tardif apparaissent avant que la page ne soit capturée. Cinq secondes est un bon point de départ ; augmentez-le si les champs produits reviennent vides. Exécutez le script avec python scraper.py et vous devriez voir du vrai balisage produit, pas la coquille vide qu'une récupération simple renvoie. Cela confirme que le rendu fonctionne avant d'écrire un seul sélecteur.

Crawlbase Crawling API

Zalando nécessite une page rendue derrière une IP de confiance, en un seul appel. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, effectue une rotation des IP résidentielles côté serveur et vous remet le HTML final, vous évitant ainsi de devoir gérer une flotte sans tête et un pool de proxies vous-même. Pointez-la vers une page produit publique sur l'offre gratuite d'abord.

Étape 2 : Analyser les champs produit avec BeautifulSoup

Une fois le HTML rendu en main, chargez-le dans BeautifulSoup et extrayez chaque champ par son sélecteur. Les pages produits Zalando disposent les détails essentiels dans une structure assez prévisible, vous pouvez donc mapper nom, marque, prix, tailles et couleur sur des sélecteurs individuels. Encapsulez l'extraction dans des helpers afin qu'un champ manquant ne fasse pas planter l'exécution.

python
from bs4 import BeautifulSoup

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def all_text(soup, selector):
    return [el.get_text(strip=True) for el in soup.select(selector)]

def scrape_product(html):
    soup = BeautifulSoup(html, "html.parser")

    sizes = all_text(soup, "[data-testid='pdp-size-picker'] [role='option']")

    return {
        "name": text_of(soup, "span.EKabf7.R_QwOV"),
        "brand": text_of(soup, "span.OBkCPz.Z82GLX"),
        "price": text_of(soup, "span.voFjEy.Km7l2y"),
        "color": text_of(soup, "[data-testid='color-name']"),
        "sizes": [s for s in sizes if s],
    }

Le helper text_of fait deux choses utiles à la fois : il interroge un seul élément et renvoie None lorsque l'élément est absent, au lieu de lever une exception sur un appel .get_text() contre rien. Le helper all_text collecte chaque correspondance pour les champs qui se répètent, ce que vous souhaitez pour les options de taille. Cela rend l'extraction résiliente lorsqu'un champ est absent sur une page donnée, ce qui est courant car tous les produits ne listent pas tous les détails.

Selectors drift

Les noms de classes de Zalando (les tokens hachés comme EKabf7 et voFjEy) sont générés et changent sans préavis. Traitez les sélecteurs ci-dessus comme un modèle de départ, pas comme un contrat. Quand un champ revient à None ou une liste vide, réinspectez la page en production dans les outils de développement de votre navigateur et mettez à jour le sélecteur. Les attributs data-testid stables ont tendance à survivre plus longtemps que les noms de classes hachés, préférez-les lorsqu'ils existent. La maintenance périodique des sélecteurs est normale pour tout scraper en production, ce n'est pas le signe que quelque chose est cassé.

Étape 3 : Tout assembler

Assemblez maintenant la récupération et l'analyse en un seul script exécutable. Récupérez le HTML rendu, transmettez-le à l'analyseur et affichez l'enregistrement structuré.

python
import json
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

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

def crawl(page_url):
    options = {"ajax_wait": "true", "page_wait": 5000}
    response = api.get(page_url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Request failed: {response['status_code']}")
    return None

def text_of(soup, selector):
    el = soup.select_one(selector)
    return el.get_text(strip=True) if el else None

def all_text(soup, selector):
    return [el.get_text(strip=True) for el in soup.select(selector)]

def scrape_product(html):
    soup = BeautifulSoup(html, "html.parser")
    sizes = all_text(soup, "[data-testid='pdp-size-picker'] [role='option']")
    return {
        "name": text_of(soup, "span.EKabf7.R_QwOV"),
        "brand": text_of(soup, "span.OBkCPz.Z82GLX"),
        "price": text_of(soup, "span.voFjEy.Km7l2y"),
        "color": text_of(soup, "[data-testid='color-name']"),
        "sizes": [s for s in sizes if s],
    }

def main():
    page_url = "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html"
    html = crawl(page_url)
    if not html:
        return
    data = scrape_product(html)
    print(json.dumps(data, indent=2, ensure_ascii=False))

if __name__ == "__main__":
    main()

Définir ensure_ascii=False dans le dump JSON maintient le signe euro et les caractères accentués lisibles au lieu de les échapper. Exécutez le script complet avec python scraper.py et vous obtenez un enregistrement structuré propre pour le produit.

À quoi ressemble le résultat

Le script affiche un enregistrement unique prêt à écrire en JSON, CSV ou dans une base de données.

json
{
  "name": "LEATHER - Handbag",
  "brand": "Zign",
  "price": "49,99 €",
  "color": "black",
  "sizes": ["One Size"]
}

Pour un article d'habillement, la liste sizes porterait la vraie gamme de tailles, par exemple ["XS", "S", "M", "L"], avec les tailles épuisées supprimées si vous filtrez sur l'état de disponibilité du sélecteur de tailles.

Passer à l'échelle sur de nombreux produits

Une page est une démonstration ; un vrai travail s'exécute sur une liste de produits. La forme reste la même : conservez une liste d'URLs produits, récupérez chacun via la Crawling API, analysez-le avec la même fonction et collectez les lignes. Comme chaque page produit partage la même structure, l'analyseur déjà écrit fonctionne sur toutes sans modifications. L'ajout clé est le rythme : une courte pause entre les requêtes évite que l'exécution ne ressemble à une rafale de trafic bot.

python
import time

products = [
    "https://en.zalando.de/zign-handbag-black-zi151h08a-q11.html",
    "https://en.zalando.de/anna-field-handbag-black-an651h0x2-q11.html",
]

results = []
for url in products:
    html = crawl(url)
    if html:
        results.append({"url": url, **scrape_product(html)})
    time.sleep(2)

with open("zalando_products.json", "w", encoding="utf-8") as f:
    json.dump(results, f, indent=2, ensure_ascii=False)

Pour trouver des URLs produits à grande échelle, scrapez les pages de catalogue public de Zalando (par exemple https://en.zalando.de/catalogue/?q=handbags) avec le même schéma récupérer-puis-analyser, collectez les liens produits, puis visitez chacun. Maintenez simplement le volume raisonnable et respectez les limites de débit abordées ci-dessous. Si le prix est votre objectif final, les enregistrements collectés s'intègrent directement dans un pipeline de renseignement tarifaire.

Rester non bloqué

Même avec le rendu géré, Zalando surveille le trafic qui ressemble à des scrapers. Quelques habitudes maintiennent une exécution en bonne santé, et elles s'appliquent à toute cible commerciale difficile.

  • Pace your requests. Marteler les pages dans une boucle serrée est le moyen le plus rapide d'être throttlé. Le time.sleep ci-dessus espace les requêtes ; variez vos cibles plutôt que de crawler un seul chemin à pleine vitesse.
  • Lean on rotation. Un pool d'IP résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels afin qu'aucune ne déclenche une limite de débit. La Crawling API gère cela pour vous ; si vous construisez votre propre infrastructure, c'est la partie à bien maîtriser.
  • Read the status codes. Une exécution qui commence à renvoyer des challenges ou des erreurs vous indique que le débit ou le niveau d'IP actuel ne suffit plus. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.

Pour le manuel de stratégie complet, consultez comment scraper des sites sans être bloqué et l'analyse approfondie sur comment contourner les captchas lors du scraping web. Si vous préférez router votre propre trafic via un pool tournant plutôt que d'utiliser l'API gérée, le Smart AI Proxy (également appelé AI Proxy) vous donne la même rotation d'IP résidentielles en tant que point de terminaison proxy drop-in. La même approche s'étend aux catalogues voisins comme AliExpress et Walmart.

Est-il légal de scraper Zalando ?

La légalité du scraping de Zalando dépend des conditions d'utilisation de Zalando, de votre juridiction et de l'usage que vous faites des données. Les conditions de Zalando restreignent l'accès automatisé, de sorte que le scraping peut contrevenir à ces conditions quelle que soit la prudence de vos outils. Aucun des codes présentés ici ne change cela ; il se contente de faire fonctionner la partie technique. Lisez les conditions d'utilisation de Zalando et son robots.txt, et traitez les deux comme la limite de ce que vous collectez.

Quelques principes à respecter. Collectez uniquement les données produits publiques : nom du produit, marque, prix, tailles disponibles et couleur que tout le monde peut voir sans compte. Respectez les attentes de débit déclarées de Zalando et maintenez votre volume de requêtes assez bas pour ne pas surcharger ses serveurs. Évitez les données personnelles, y compris tout ce qui est lié à des individus identifiables tels que les profils des évaluateurs ou les informations de compte. Si vous prévoyez de réutiliser les données commercialement, obtenez une autorisation ou un accord officiel plutôt que de supposer que le silence vaut consentement.

Ce guide se limite délibérément aux pages produits publiques parce que c'est la ligne qui rend le travail défendable. Il ne couvre pas ce qui se trouve derrière une connexion, les données de compte ou de commande, les données personnelles, les pages protégées par une authentification, ni aucune tentative de contourner l'authentification. Pour une utilisation à grande échelle ou commerciale, préférez une API officielle ou un accord de données avec Zalando plutôt qu'un scraper plus astucieux. Les données produits publiques uniquement est la règle qui vous maintient du bon côté des conditions et de la loi.

Récapitulatif

Points clés

  • Zalando is client-side rendered. Une récupération simple renvoie une coquille vide ou un défi, vous devez donc rendre la page avant de l'analyser.
  • You need rendering and a trusted IP together. La Crawling API avec un token JS fait les deux en un seul appel ; ajax_wait et page_wait contrôlent combien de temps elle attend le contenu.
  • BeautifulSoup does the extraction. Mappez le nom du produit, la marque, le prix, les tailles et la couleur sur les sélecteurs actuels, préférez les attributs data-testid stables et attendez-vous à ce que les noms de classes hachés évoluent.
  • Scale by looping URLs with pacing. Le même analyseur fonctionne sur chaque produit, donc un vrai travail n'est qu'une liste de liens plus une courte pause entre les requêtes.
  • Stay on public data. Respectez les CGU et le robots.txt de Zalando, préférez une API officielle pour une utilisation en volume ou commerciale, et ne touchez jamais aux comptes, aux pages protégées par une authentification ou aux informations personnelles.

Foire aux questions

Pourquoi une simple requête ne renvoie-t-elle aucune donnée de Zalando ?

Parce que Zalando rend son contenu produit côté client avec JavaScript. Le HTML initial est une coquille qui ne se remplit qu'après l'exécution des scripts de la page dans un navigateur, donc une requête HTTP brute renvoie le statut 200 avec les champs produits vides, ou un défi bot au lieu de la page. Pour obtenir des données réelles, vous devez d'abord rendre la page, ce que gère le token JS de la Crawling API.

Ai-je besoin du token normal ou du token JS pour Zalando ?

Le token JS. Le token normal récupère le HTML statique, qui sur Zalando est la même coquille vide qu'une récupération simple renvoie. Le token JS rend la page dans un vrai navigateur avant de renvoyer le HTML, de sorte que le nom du produit, la marque, le prix, les tailles et la couleur sont présents lorsque BeautifulSoup les analyse.

Mes sélecteurs renvoient None ou des listes vides. Qu'est-ce qui a changé ?

Très probablement le balisage de Zalando. Ses noms de classes hachés comme EKabf7 et voFjEy sont générés et changent sans préavis, les sélecteurs qui fonctionnaient le mois dernier peuvent donc se casser. Réinspectez une page produit en production dans les outils de développement de votre navigateur et mettez à jour les sélecteurs. Préférez les attributs data-testid stables lorsqu'ils existent, car ils survivent aux refontes plus longtemps que les classes hachées.

Puis-je utiliser Python au lieu de Puppeteer ou Node.js pour scraper Zalando ?

Oui. Comme la Crawling API rend la page côté serveur et renvoie le HTML final, vous n'avez pas du tout besoin d'exécuter un navigateur sans tête localement. Un petit script Python avec le client crawlbase et BeautifulSoup suffit, c'est toute l'approche de ce guide. Cela maintient le scraper léger et facile à planifier.

Comment scraper de nombreux produits Zalando sans être bloqué ?

Maintenez votre débit de requêtes par IP bas, ajoutez une courte pause entre les requêtes et variez vos cibles plutôt que de boucler sur un seul chemin. Routez via des IP résidentielles tournantes afin qu'aucune adresse unique ne déclenche une limite de débit ; la Crawling API gère la rotation et un pool d'IP de confiance pour vous. Surveillez les codes de statut et ralentissez quand vous commencez à voir des défis.

Est-il légal de scraper les données produit de Zalando ?

Cela dépend des conditions d'utilisation de Zalando, de votre juridiction et de votre usage des données. Ce guide se limite aux données produits publiques (nom, marque, prix, tailles, couleur) et vous demande de respecter le robots.txt et les CGU. Il ne couvre pas les données de compte, les données personnelles, les pages protégées par une authentification ni le contournement de l'authentification. Pour une utilisation en volume ou commerciale, une API officielle ou un accord de données est la bonne voie, pas un scraper.

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