Python递归调用解析分页API数据失效问题排查
问题原因
你的parse()方法是生成器函数(内部使用了yield关键字),直接写self.parse()做递归调用时,只会创建一个新的生成器对象,不会自动迭代产出这个对象里的内容,下一页解析出来的所有数据都会被直接丢弃,外层的遍历循环根本拿不到。
从你打印的日志能看到递归调用确实触发了,但因为没有对递归返回的生成器做迭代、透传元素的操作,所以只有第一页数据被正常yield出来。
另外原代码还有几个潜在隐患:
- 初始化请求如果触发异常,
self.response不会被赋值,后续调用parse()会直接报属性不存在的错误 - 所有请求都没有调用
raise_for_status(),如果接口返回4xx/5xx状态码,直接调用.json()会报错 - 直接用字典下标取值,接口如果返回异常结构缺少
Items/NextPageLink字段会直接触发KeyError - 请求下一页的逻辑没有做异常捕获,分页请求失败会直接中断整个流程
修正方法
核心改动是递归调用生成器时,用yield from语法把递归生成器的所有元素透传到外层(Python 3.3及以上版本支持),同时补全异常和边界判断。
修正后的完整代码:
import requests from requests.exceptions import HTTPError class MyParser(): def __init__(self, start_url): self.start_url = start_url self.response = None def _send_request(self, url): # 统一封装请求逻辑,处理异常 try: resp = requests.get(url) resp.raise_for_status() return resp except HTTPError as http_err: print(f"HTTP请求错误: {http_err}") return None except Exception as err: print(f"请求异常: {err}") return None def parse(self): # 首次调用时请求起始接口 if self.response is None: self.response = self._send_request(self.start_url) if not self.response: return resp_data = self.response.json() # 遍历产出当前页数据 for item in resp_data.get("Items", []): yield {item["Thing"]: item["Entry"]} # 处理下一页 next_page_link = resp_data.get("NextPageLink") if next_page_link: self.response = self._send_request(next_page_link) if self.response: # 关键:透传递归生成器的所有元素 yield from self.parse()
测试调用方式:
if __name__ == "__main__": parser = MyParser("替换为实际API起始地址") for item in parser.parse(): print(item)
原输出的对应解释
你之前运行时看到的输出,正好对应问题点:
- 打印
Called outer、第一页数据:第一页生成器逻辑正常执行,数据成功yield到外层 - 打印
about to call again、Called:递归调用的代码确实执行了,但是返回的生成器没有被迭代,下一页的所有yield内容都没有传递出来,所以外层循环拿不到后续数据。
内容的提问来源于stack exchange,提问作者abinitio
相关产品推荐
相关产品推荐

