如何在未知符合条件页数时,从API获取指定日期范围的数据集
首先得给你吃个定心丸:你当前的请求里已经带上了receivedDateFrom和receivedDateTo这两个日期参数,正常情况下,API应该只会返回符合这个日期范围的分页数据,而不是把整个数据集的所有页都返回给你再让你自己过滤。所以你现在的循环其实是在拉取所有符合条件的结果页,并没有在做无用功遍历无关页面——之前循环停不下来,大概率是终止条件的问题,不是在遍历所有页。
接下来帮你分析和优化代码:
你的代码当前的核心问题
你用if not response_data: break作为终止条件,但很多API在没有更多数据时,不会返回空数组,可能会返回一个包含空数据字段的对象(比如{"items": []}),或者返回结构完整但内容为空的非空对象,这就导致你的终止条件永远触发不了,循环无限进行。
优化方案
我们可以从两个方向优化终止逻辑,同时让代码更健壮:
1. 优先利用API的分页元数据(如果有的话)
很多API会在响应里返回分页相关的元数据,比如totalPages(总页数)、hasNextPage(是否有下一页)、totalItems(总条数)这类字段。如果你的API返回这些,直接用这些字段判断会更准确。比如响应里有hasNextPage: false,就可以直接终止循环。
2. 基于返回数据长度的健壮终止条件
如果API没有返回分页元数据,我们可以通过判断当前页返回的数据数量来判断是否是最后一页:如果当前页返回的数据条数小于你设置的page_size,说明这就是最后一页了(除非总数据量刚好是page_size的整数倍,这时候就靠空数据的条件来终止)。
另外,把手动拼接JSON字符串改成用requests的json参数自动处理,既不容易出错,代码可读性也更高。
修改后的完整代码
import requests import datetime start_date = datetime.datetime(2016, 10, 1).isoformat() end_date = datetime.datetime(2017, 9, 30).isoformat() page_size = 2000 page_number = 1 all_data = [] # 初始化存储所有数据的列表 while True: # 用字典构造请求体,让requests自动处理JSON序列化 payload = { "receivedDateFrom": start_date, "receivedDateTo": end_date, "pageSize": page_size, "pageNumber": page_number } # 用json参数传递请求体,替代手动拼接字符串 response = requests.post( url, headers=headers, verify=True, json=payload ) # 主动抛出请求错误(比如404、500),避免默默失败 response.raise_for_status() response_data = response.json() # 终止条件1:当前页没有返回任何数据,直接退出循环 if not response_data: break all_data.extend(response_data) # 终止条件2:如果当前页返回的数据条数小于page_size,说明这是最后一页 if len(response_data) < page_size: break page_number += 1
最后再澄清你的核心疑问
你担心“遍历所有页”是多余的——因为你已经通过请求参数告诉API只返回指定日期范围内的数据,所以你循环拉取的每一页都是符合要求的结果,没有在遍历无关页面。之前的循环停不下来,完全是终止条件不够健壮导致的,调整之后就可以正常结束循环了。
备注:内容来源于stack exchange,提问作者swilson

