Retour à l'accueil

API WB Ozon : gestion des erreurs 429 et 50x

L'article décrit des stratégies pour gérer les erreurs 429 et 50x lors du travail avec les API Wildberries et Ozon. Couvre la logique de réessai avec backoff, le batching quotidien des requêtes et la surveillance en arrière-plan pour une automatisation complète de la collecte de données.

Sans erreurs 429 des API de places de marché : code et tactiques
Advertisement 728x90

Gestion des erreurs 429 et 50x dans les API Wildberries et Ozon

Lors du scraping de données via les API Wildberries et Ozon, les développeurs rencontrent souvent les erreurs 429 (trop de requêtes) et 50x (erreurs serveur). Ces problèmes surgissent en cas de surcharge des endpoints. La solution habituelle du support technique repose sur des tentatives de réessai. Nous allons explorer trois stratégies solides : gestion basique des réessais, optimisation du volume de requêtes et surveillance avec rechargements partiels.

Gestion basique des réessais

Commencez par considérer les erreurs 429 et 50x comme des incidents attendus. Implémentez une logique de réessai avec backoff exponentiel et analysez les en-têtes comme X-Ratelimit-Retry. Cela réduit les blocages et renforce la résilience.

Voici un exemple de fonction pour les requêtes POST avec réessais :

Google AdInline article slot
def get_oz(url, heads, params, max_retries=5, timeout=30):
    result = {}
    for retries in range(1, max_retries + 1):  
        
        try:
            response = requests.post(url, headers=heads, json=params, timeout=timeout)
        except requests.RequestException as e:
            print(f'!!! Erreur réseau à la tentative {retries}: {e}!!!')
            time.sleep(2 * retries)
            continue  
                
        # 200 signifie succès    
        if response.status_code == 200:
            return response.json()
            
        # 429 - Trop de requêtes, pause intelligente et réessai
        elif response.status_code == 429:    
            pause_time = 2 ** retries
            
            # X-Ratelimit-Retry - Astuce Wildberries, Ozon pourrait l'ajouter un jour
            if 'X-Ratelimit-Retry' in response.headers:
                pause_time = int(response.headers['X-Ratelimit-Retry']) + 5
            print(f'get_oz: ! -Trop de requêtes- à la tentative {retries}. Pause {pause_time} sec')
            time.sleep(pause_time)
        
        # Erreurs 5xx - pause et réessai                    
        elif 500 <= response.status_code < 600:
            pause_time = 2 ** retries
            print(f'get_oz: ! -Erreur {response.status_code}- à la tentative {retries}. Pause {pause_time} sec')
            time.sleep(pause_time)
        
        # Toute autre erreur - abandon !                
        else:
            print(f'get_oz: !!! Échec de récupération des données API ! code: {response.status_code}')
            return None


    print(f'get_oz: !!! Toutes les {max_retries} tentatives ont échoué')
  
    return None
  • 5 réessais couvrent la plupart des charges typiques.
  • Gérez les boucles de pagination (offset/page) à un niveau supérieur.
  • En cas d'échec total, attendez une heure ou plus.

Cette approche s'intègre parfaitement dans n'importe quel pipeline ETL pour API.

Optimisation du volume de données

Les grosses requêtes (comme les transactions d'une semaine) déclenchent des erreurs sur les pages de pagination ultérieures. Fractionnez-les en petits lots indépendants : par jour, catégorie ou filtres. Sauvegardez chaque lot dans votre base de données immédiatement — la perte d'un lot n'efface pas vos progrès.

Avantages :

Google AdInline article slot
  • Moins de pages par requête (1–3 au lieu de 20).
  • Réessais indépendants par lot.
  • Sauvegardes partielles en cas d'échec.

Exemple : Chargement des transactions Ozon par jour :

date_from = today() - timedelta(days=7)
date_to = today() - timedelta(days=1)
current_date = date_from
delta = timedelta(days=1)

# Boucle sur les jours de date_from à date_to
while current_date <= date_to:  
    transactions_oneday = pd.DataFrame([])           
    url = "https://api-seller.ozon.ru/v3/finance/transaction/list"
    ipage = 1
    all_pages_data = []
    while True:
        data = {
            "filter": {
                "date": {
                    "from": str(current_date) + "T00:00:00.000Z",
                    "to": str(current_date) + "T23:59:59.999Z"
                }
            },
            "page": ipage,
            "page_size": 1000
            }
        dd = []
        apioz_response = get_oz(url, headers, data, 5)
        if len(apioz_response) > 0 :
            dd = apioz_response['result']['operations']
            all_pages_data.extend(dd)
        else:
            print(f'!!! Réponse API vide')    

        # Si la page a <1000 lignes, c'est la dernière - sortie    
        if len(dd) < 1000: break

        ipage +=1
            
    transactions_oneday = pd.DataFrame(all_pages_data)        
    # Export immédiat vers la DB de ce qui a été récupéré de l'API
    export_to_db('oz_transactions', transactions_oneday)

    # Jour suivant
    current_date += delta    

Les boucles imbriquées peuvent sembler brouillonnes, mais la fiabilité explose.

Surveillance et rechargements partiels

Pour une automatisation complète, ajoutez un filet de sécurité : surveillance en arrière-plan. Après le lancement principal (disons 6–7 h du matin), vérifiez les logs/base de données toutes les heures (8–12 h).

Google AdInline article slot
  • Vérifiez le statut de la dernière tâche.
  • Contrôlez l'intégrité des données (lacunes de dates).
  • Déclenchez des réessais ciblés uniquement pour les chunks manquants.

Cela minimise les interventions manuelles, surtout pour les mises à jour quotidiennes.

Points clés à retenir

  • Utilisez un backoff exponentiel avec les en-têtes de réessai pour les 429.
  • Fractionnez les grosses requêtes en lots quotidiens/filtrés avec sauvegardes immédiates.
  • Ajoutez une surveillance horaire après collecte pour combler les trous.
  • 5 réessais couvrent 95 % des échecs ; les flops totaux attendent 1 h+.
  • Intégrez dans l'ETL sans liens serrés à la pagination.

— Editorial Team

Advertisement 728x90

Lire ensuite