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 :
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 :
- 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).
- 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
Aucun commentaire pour le moment.