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

Python Requests 2.27.1分页循环中URL重复追加查询参数问题

问题根因
  • 首先明确requests库的既定行为:如果传入request()方法的url本身携带查询字符串,方法不会清空原有查询参数,会将params字典传入的参数直接追加到现有查询串末尾,不会做去重、覆盖处理。简单验证即可复现该逻辑:执行requests.get('https://httpbin.org/get?page=0', params={'page':1}),最终请求URL为https://httpbin.org/get?page=0&page=1,服务端默认会读取第一个重复参数的值,和你遇到的现象完全一致。
  • 你本地针对httpbin的测试代码运行正常,核心原因是测试代码中url变量从头到尾都是无参数的基础路径,从未被污染,因此每次都是基于干净URL拼接参数,不会出现重复追加。
  • 业务代码出现参数持续追加,唯一直接原因是:while循环进入第二轮及之后,传入session.request()的url变量已经是上一轮请求生成的带查询字符串的完整URL,不再是初始传入的无参数基础路径。

结合你贴的代码逻辑,90%以上概率是你实际运行的代码中存在遗漏的URL赋值逻辑(比如之前写过从响应头、响应体提取next链接的逻辑未清理干净,存在url = response.url、url = result['next']这类赋值),把上一轮的带参URL赋值给了循环内的url变量;剩余低概率原因是Session挂载了自定义请求钩子、认证类、传输适配器,错误复用了上一次的请求对象导致URL被重复拼接参数。

你观察到的“page参数卡在1无法继续推进”现象也和这个逻辑完全吻合:第二轮请求的URL已经携带page=0,即使params里设置page=1,最终URL里会同时存在page=0和page=1,服务端读取第一个page=0返回对应页数据,你的代码读取响应里的page=0,又会把params的page设为1,进入死循环重复追加page=1&size=100参数。

合规解决方案

不要使用url.split('?')[0]这类临时规避方案,按以下步骤修复:

  1. 先定位污染源:在while循环内调用session.request()的前一行加调试日志,打印当前传入的url值,确认第二轮开始url是否已携带查询参数,回溯找到给url赋值带参地址的代码段并删除——你的inline分页逻辑完全靠params控制翻页参数,不需要从响应中提取翻页URL。
  2. 从根源避免URL被污染:进入while循环前,将初始传入的基础URL存为固定变量,同时复制参数副本避免修改外部传入的字典引用,核心修改示例如下:
    import json as native_json
    from urllib.parse import urlparse, parse_qs, urlencode
    
    def __request(self, method, url, params=None, data=None, json=None):
        return_data = []
        num_iterations = 1
        pagination_type = None
        
        # 解析原始URL,固定干净的基础路径,把自带的查询参数合并到请求参数里
        parsed_url = urlparse(url)
        base_url = f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path}"
        # 初始化参数副本,避免修改外部传入的params引用造成副作用
        request_params = {}
        if parsed_url.query:
            request_params.update(parse_qs(parsed_url.query, keep_blank_values=True))
        if params is not None:
            request_params.update(params)
    
        while True:
            # 永远用干净的base_url发请求,避免URL带参导致参数追加
            response = self.session.request(method, base_url, params=request_params, data=data, json=json)
            self.__check_response_for_error(response)
            if self.__response_has_no_content(response):
                return None
    
            try:
                result = response.json()
            except native_json.decoder.JSONDecodeError:
                return response.content.decode('utf-8')
    
            if num_iterations == 1:
                pagination_type = self.__pagination_type(response.headers, result)
    
            if pagination_type == 'inline':
                return_data += result['data']
                count = result['count']
                page = result['page']
                size = result['size']
                if size * (page + 1) >= count:
                    break
                else:
                    # 仅修改参数副本,不影响外部传入的原始参数
                    request_params['page'] = page + 1
                    request_params['size'] = size
            elif pagination_type == 'audit':
                # 原有业务逻辑保持不变,涉及翻页参数修改统一操作request_params
                pass
            elif pagination_type == 'report':
                # 原有业务逻辑保持不变
                pass
            elif pagination_type == 'secmgr':
                # 原有业务逻辑保持不变
                pass
            else:
                return_data = result
                break
    
            num_iterations += 1
    
        return return_data
    
  3. 修复后验证:在调用session.request前打印base_url和request_params,确认每一轮请求的base_url都是无参数的基础路径,request_params里的page参数按预期递增,最终生成的请求URL不会出现重复参数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:18:20