返回首页

API WB Ozon:处理 429 和 50x 错误

文章描述了在使用 Wildberries 和 Ozon API 时处理 429 和 50x 错误的相关策略。涵盖带退避的重试逻辑、每日请求批处理,以及后台监控,实现完整数据收集自动化。

避免电商平台 API 的 429 错误:代码和策略
Advertisement 728x90

Wildberries 和 Ozon API 中 429 和 50x 错误的处理策略

在从 Wildberries 和 Ozon API 抓取数据时,开发者经常遇到 429(请求过多)和 50x(服务器错误)问题。这些错误通常因端点负载过重而出现。技术支持的常规解决方案是重试。我们将介绍三种实用策略:基础重试机制、优化请求量,以及带部分重载的监控。

基础重试机制

首先,将 429 和 50x 错误视为正常波动。实现带有指数退避的重试逻辑,并解析如 X-Ratelimit-Retry 等头部信息。这能有效减少封禁风险并提升系统韧性。

以下是带重试的 POST 请求示例函数:

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'!!! Network error on attempt {retries}: {e}!!!')
            time.sleep(2 * retries)
            continue  
                
        # 200 means success    
        if response.status_code == 200:
            return response.json()
            
        # 429 - Too many requests, smart pause and retry
        elif response.status_code == 429:    
            pause_time = 2 ** retries
            
            # X-Ratelimit-Retry - Wildberries trick, Ozon might add it someday
            if 'X-Ratelimit-Retry' in response.headers:
                pause_time = int(response.headers['X-Ratelimit-Retry']) + 5
            print(f'get_oz: ! -Too many requests- on attempt {retries}. Pausing {pause_time} sec')
            time.sleep(pause_time)
        
        # 5xx errors - pause and retry                    
        elif 500 <= response.status_code < 600:
            pause_time = 2 ** retries
            print(f'get_oz: ! -Error {response.status_code}- on attempt {retries}. Pausing {pause_time} sec')
            time.sleep(pause_time)
        
        # Any other error - bail out!                
        else:
            print(f'get_oz: !!! API data fetch failed! code: {response.status_code}')
            return None


    print(f'get_oz: !!! All {max_retries} attempts failed')
  
    return None
  • 5 次重试能应对大多数常见负载。
  • 在更高层处理分页循环(offset/page)。
  • 完全失败时,退避 1 小时或更长。

这种机制可无缝嵌入任何 API ETL 管道。

优化数据量

大批量请求(如一周交易记录)会在后续分页时触发错误。将它们拆分成小而独立的批次:按天、类别或过滤条件。每个批次立即保存到数据库——丢失一个不会影响整体进度。

优势:

Google AdInline article slot
  • 每个请求页数减少(1–3 页 vs. 20 页)。
  • 每个批次独立重试。
  • 失败时支持部分保存。

示例:按天加载 Ozon 交易记录:

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

# Loop through days from date_from to 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'!!! Empty API response')    

        # If page has <1000 rows, it's the last - break    
        if len(dd) < 1000: break

        ipage +=1
            
    transactions_oneday = pd.DataFrame(all_pages_data)        
    # Export to DB right away what we got from API
    export_to_db('oz_transactions', transactions_oneday)

    # Next day
    current_date += delta    

嵌套循环看似复杂,但可靠性大幅提升。

监控与部分重载

为实现全自动化,添加安全网:后台监控。主要任务结束后(例如凌晨 6–7 点),每小时检查日志/数据库(上午 8–12 点)。

Google AdInline article slot
  • 检查上一次任务状态。
  • 验证数据完整性(日期缺口)。
  • 针对缺失片段触发定向重试。

这能最大限度减少手动干预,尤其适用于日常更新。

关键要点

  • 对 429 使用指数退避结合重试头部。
  • 大请求拆分成按天/过滤批次,并立即保存。
  • 采集后添加小时级监控填补缺口。
  • 5 次重试覆盖 95% 失败;彻底失败延时 1 小时以上。
  • 无需紧密绑定分页,直接集成到 ETL。

— Editorial Team

Advertisement 728x90

继续阅读