Python高效安全处理大型JSON API分页及响应问题
处理大型分页JSON REST API的实践解答
针对你对接大型分页API时遇到的问题,逐一解答如下:
1. 正确遍历所有分页
利用startIndex和resultsPerPage参数,通过循环请求直到获取不到新数据即可。建议先确认API是否返回总记录数(比如totalItems字段),可以更精准地终止循环;如果没有总记录数,就以返回的items为空作为终止条件。
示例代码:
import requests base_url = "https://example.com/api" results_per_page = 100 # 根据API限制调整,平衡请求次数和单次响应大小 start_index = 0 all_items = [] while True: params = { "startIndex": start_index, "resultsPerPage": results_per_page } try: response = requests.get(base_url, params=params, timeout=10) response.raise_for_status() data = response.json() except Exception as e: print(f"第{start_index}页请求失败: {str(e)}") start_index += results_per_page continue current_items = data.get("items", []) if not current_items: break all_items.extend(current_items) # 若API返回总记录数,提前终止循环 total = data.get("totalItems") if total and len(all_items) >= total: break start_index += results_per_page
2. 处理JSON解析失败
用try-except块包裹response.json()调用,同时还要处理HTTP请求异常(比如超时、4xx/5xx错误),避免程序直接崩溃。
示例代码片段:
try: response = requests.get(base_url, params=params, timeout=10) response.raise_for_status() # 触发HTTP错误(如404、500) try: data = response.json() except ValueError: # JSONDecodeError是ValueError的子类 print(f"第{start_index}页返回非JSON格式内容,跳过") continue except requests.exceptions.RequestException as e: print(f"请求第{start_index}页出错: {str(e)}") # 可添加重试逻辑,比如重试3次后跳过 continue
3. 避免存储重复记录
根据数据存储方式,有几种常用方案:
- 内存中去重:用字典以唯一标识(如
item["id"])为键存储数据,自动覆盖重复项:unique_items = {} for item in current_items: item_id = item["id"] unique_items[item_id] = item # 重复id会被最新值覆盖 # 最终去重后的列表:list(unique_items.values()) - 数据库去重:给
id字段添加唯一约束,插入时使用INSERT OR IGNORE(SQLite)或ON CONFLICT DO NOTHING(PostgreSQL)语法,自动忽略重复记录。 - 文件存储去重:每次写入前先加载已存储的id集合,检查当前item的id是否存在,仅写入新记录。
4. Python处理大型API响应的最佳实践
- 合理设置分页大小:不要过小(导致请求次数过多)或过大(单次响应占用内存过高),一般建议100-1000条/页,具体参考API的限制说明。
- 添加重试机制:针对网络波动、API限流等情况,实现指数退避重试(比如用
tenacity库),避免单次失败导致流程中断。 - 增量处理与存储:不要一次性把所有数据加载到内存,处理完一页就存储一页,降低内存占用。
- 异步请求优化:如果API允许并发请求,用
aiohttp替代requests实现异步请求,提升数据获取效率,但需注意控制并发数,避免触发API限流。 - 日志与监控:记录每一页的请求状态、获取条数等信息,方便后续排查问题。
- 遵守API限流规则:查看API文档中的速率限制,设置请求间隔(比如
time.sleep(1)),避免被封禁。 - 数据验证:访问item字段前先检查是否存在(比如用
item.get("id")),避免KeyError导致程序崩溃。
内容的提问来源于stack exchange,提问作者Lucus_sathyabama
相关产品推荐
相关产品推荐

