You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python分页获取API全量数据时出现签名不匹配错误求助

问题排查:API分页请求签名不匹配错误

你遇到的签名不匹配问题,主要是因为签名生成逻辑、时间戳处理和分页循环的几个错误导致的。我先帮你拆解问题,再给出修正后的代码。

首先看你的代码和输出,能发现几个明显的问题:

核心错误原因

  1. 签名计算包含了旧的Signature字段
    从你打印的concatenated内容可以看到,每次生成签名时,参数里都包含了上一次请求的Signature值。而API的签名逻辑肯定是要求只对除Signature外的其他参数进行哈希计算,把旧签名加进去会导致计算出来的新签名和API预期的完全不符。

  2. 时间戳没有随请求更新
    你只在函数开头生成了一次Timestamp,整个分页循环都用同一个时间戳。很多API会校验请求时间戳的有效性(比如必须是当前时间的几分钟内),重复使用旧时间戳很容易触发签名验证失败。

  3. 分页逻辑严重错误

    • 你的代码在第一次请求后就直接return page_json,根本不会执行后续的分页请求;
    • 循环内的try-except块重复发送请求,逻辑混乱,也没有判断什么时候停止分页(比如返回的数据不足500条时应该终止循环)。

修正后的完整代码

import datetime
import urllib.parse
import requests
import time
from hmac import HMAC
from hashlib import sha256

def get_data(userid, api_key, action, pagination=True):
    endpoint = 'https://example.com'
    all_data = []  # 用来存储所有分页返回的数据
    
    # 定义基础参数,这些参数在分页过程中不会变化
    base_params = {
        'UserID': userid,
        'Version': '1.0',
        'Action': action,
        'Format': 'JSON'
    }
    
    if not pagination:
        # 不分页的情况,直接请求默认数量
        params = base_params.copy()
        # 生成当前请求的时间戳
        timestamp = datetime.datetime.now().replace(microsecond=0).isoformat() + '+08:00'
        params['Timestamp'] = timestamp
        
        # 生成签名:只对除Signature外的参数排序拼接
        sorted_params = sorted(params.items())
        concatenated = urllib.parse.urlencode(sorted_params)
        params['Signature'] = HMAC(api_key.encode('utf-8'), concatenated.encode('utf-8'), sha256).hexdigest()
        
        try:
            response = requests.get(endpoint, params=params)
            response.raise_for_status()  # 触发HTTP错误,比如4xx/5xx
            return response.json()
        except requests.exceptions.ConnectionError:
            print("连接被拒绝!5秒后重试...")
            time.sleep(5)
            # 重试一次
            response = requests.get(endpoint, params=params)
            response.raise_for_status()
            return response.json()
    
    # 分页获取数据的逻辑
    page = 0
    limit = 500
    while True:
        # 每次请求都复制基础参数,避免污染原参数
        params = base_params.copy()
        
        # 每次请求都生成新的时间戳
        timestamp = datetime.datetime.now().replace(microsecond=0).isoformat() + '+08:00'
        params['Timestamp'] = timestamp
        params['Limit'] = limit
        params['Offset'] = limit * page
        
        # 生成签名:注意这里只排序拼接除Signature外的参数
        sorted_params = sorted(params.items())
        concatenated = urllib.parse.urlencode(sorted_params)
        params['Signature'] = HMAC(api_key.encode('utf-8'), concatenated.encode('utf-8'), sha256).hexdigest()
        
        try:
            response = requests.get(endpoint, params=params)
            response.raise_for_status()
            page_json = response.json()
            
            # 假设数据存储在Data字段,根据你的API实际结构调整
            current_page_data = page_json.get('Data', [])
            if not current_page_data:
                # 没有数据了,终止循环
                break
            
            all_data.extend(current_page_data)
            
            # 如果当前页返回的数据数量小于limit,说明是最后一页
            if len(current_page_data) < limit:
                break
            
            page += 1
            time.sleep(1)  # 加个小延迟,避免请求太频繁触发API限流
        except requests.exceptions.ConnectionError:
            print("连接被拒绝!5秒后重试当前页...")
            time.sleep(5)
            continue  # 重试当前页,不递增page
        except requests.exceptions.HTTPError as e:
            print(f"请求出错:{e}")
            break
    
    # 返回包含所有数据的结构,和API返回格式保持一致
    return {'Data': all_data}

关键修改点说明

  1. 签名生成逻辑修复
    每次生成签名前,只对Timestamp、Offset、Limit等必要参数排序拼接,完全排除Signature字段,确保和API的签名计算规则一致。

  2. 动态更新时间戳
    在每次分页请求时都重新生成当前时间的时间戳,避免因时间戳过期或重复导致的验证失败。

  3. 正确的分页循环逻辑

    • 用all_data收集所有分页的数据,直到返回数据为空或者数量不足Limit时停止循环;
    • 移除了冗余的重复请求代码,优化了错误处理逻辑;
    • 添加了请求间隔,防止触发API的限流机制。
  4. 参数隔离
    使用base_params存储不变的参数,每次请求都复制一份,避免参数被污染(比如上次的Signature残留)。

内容的提问来源于stack exchange,提问作者AnalyticsPy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:05:45