Python Requests调用API仅返回单条数据而非多条的问题排查
NFZ API批量抓取与CSV写入问题解决方案
核心问题分析
- 单合同数据/重复问题:大概率是文件打开模式用了
'w'(覆盖写入),每次处理新合同都会清空之前的数据;或者分页循环缩进错误,只执行了一次合同号的分页请求;也可能是分页参数没正确递增,反复请求第一页数据。 - 合同号缺失:没有在每条数据中注入对应的合同号字段,或者写入CSV时没把合同号放在首列。
修正后的代码实现
import requests import csv # 替换成你的实际合同号列表 contract_numbers = ['CTR-001', 'CTR-002', 'CTR-003'] # 替换成NFZ API的实际地址 api_url = "https://api.nfz.gov.pl/your-endpoint" # 先收集所有数据,避免频繁写入文件导致覆盖 all_records = [] for contract_id in contract_numbers: current_page = 1 while True: # 构造请求参数,包含合同号和分页信息 request_params = { 'contract': contract_id, 'page': current_page, 'items_per_page': 25 } # 发送请求,捕获异常避免程序崩溃 try: resp = requests.get(api_url, params=request_params, timeout=10) resp.raise_for_status() api_data = resp.json() except requests.exceptions.RequestException as e: print(f"请求合同{contract_id}第{current_page}页失败: {e}") break # 检查当前页是否有数据,没有就终止分页循环 if not api_data.get('data', []): break # 给每条数据添加合同号,放在最前面 for record in api_data['data']: # 把合同号插入到字典首位 formatted_record = {'合同号': contract_id, **record} all_records.append(formatted_record) current_page += 1 # 写入CSV文件 if all_records: # 生成表头,确保合同号在首列 header = ['合同号'] + [key for key in all_records[0].keys() if key != '合同号'] with open('nfz_contract_data.csv', 'w', newline='', encoding='utf-8') as csv_file: writer = csv.DictWriter(csv_file, fieldnames=header) writer.writeheader() writer.writerows(all_records) print("数据写入完成") else: print("未获取到任何数据")
关键优化点说明
- 避免文件覆盖:先把所有合同的所有页数据收集到列表
all_records,最后一次性写入CSV,彻底解决覆盖问题。 - 合同号首列实现:通过字典解包将合同号字段插入到每条数据的最前面,配合自定义表头保证首列位置。
- 分页逻辑修复:每个合同单独处理分页,
current_page在循环内递增,直到API返回空数据时停止,确保抓取所有页。 - 异常处理:添加请求超时和异常捕获,避免单个请求失败导致整个程序中断。
额外建议
- 核对NFZ API的分页参数:部分API可能用
offset/limit而非page/items_per_page,需和API文档保持一致。 - 添加请求延迟:如果API有速率限制,在循环内加入
time.sleep(0.5)避免触发封禁。 - 增量写入(可选):如果数据量极大,可改用
'a'模式分批次写入,但要注意表头只写一次。
内容的提问来源于stack exchange,提问作者Michael Wiz
相关产品推荐
相关产品推荐

