使用Python asyncio下载雅虎财经期权报价批量请求出错如何排查
雅虎财经期权爬虫并发异常定位与修复方案
问题瓶颈定位步骤
- 第一步:检查所有请求的响应状态
你当前代码拿到响应后直接调用response.json(),未判断请求是否成功。雅虎财经有严格的反爬限流规则,并发请求量大时会返回429(请求过多)、503(服务不可用)、403(禁止访问)等状态码,直接解析非200响应的内容必然报错。可以在处理响应前先打印response.status和对应的请求URL,统计异常状态码的占比,确认是否被反爬拦截。 - 第二步:检查异常捕获逻辑完整性
当前你使用asyncio.gather(*tasks)时未设置return_exceptions=True,只要任意一个请求出现超时、连接断开等异常,整个gather会直接抛出异常,后续所有请求结果都无法正常处理,导致批量返回数据缺失。 - 第三步:统计并发连接数是否超限
aiohttp默认的最大并发连接数为100,你同时发起300-400个请求时,超出的请求会排队甚至超时,同时本地端口频繁占用释放也会引发连接异常。另外雅虎服务端也会限制单IP的并发连接数,超过阈值直接拒绝请求。 - 第四步:排查事件循环与Session使用是否合理
你当前代码在循环中多次调用asyncio.run(),每次调用都会重新创建、销毁事件循环,开销极大且容易引发资源泄漏。同时每个ticker的二次请求都单独创建ClientSession,没有复用TCP连接,进一步放大了连接异常的概率。 - 第五步:校验数据对应关系是否错位
你当前将请求成功的ticker和到期日分别存入两个独立列表,通过索引对应,一旦某个请求失败跳过,后续的索引会全部错位,导致拿到的到期日和ticker不匹配,二次请求返回错误数据。
核心修复方案
- 统一管理并发数,创建
ClientSession时设置并发限制:
import aiohttp # 并发数可根据测试调整为20-50之间,避免触发限流 connector = aiohttp.TCPConnector(limit=30) async with aiohttp.ClientSession(connector=connector, headers={'User-Agent': ua}) as session: # 所有请求复用同一个session,减少连接开销
- 给
asyncio.gather添加异常捕获参数,单独处理失败请求:
# 开启return_exceptions,单个请求异常不会影响整个批次的结果返回 responses = await asyncio.gather(*tasks, return_exceptions=True) for idx, resp in enumerate(responses): ticker = tickers[idx] # 先判断是否是请求层面的异常 if isinstance(resp, Exception): print(f"请求{ticker}异常:{str(resp)}") # 可将异常请求加入重试队列后续处理 continue # 再判断响应状态是否正常 if resp.status != 200: print(f"请求{ticker}返回状态码{resp.status},响应内容:{await resp.text()}") continue # 最后解析响应数据 try: data = await resp.json() except Exception as e: print(f"解析{ticker}数据失败:{str(e)}") continue
- 整合所有异步逻辑到同一个主函数,只调用一次
asyncio.run(),不要循环创建事件循环。 - 存储数据时将ticker和对应到期日绑定为字典或元组,避免索引错位。
- 准备多个User-Agent轮询使用,避免单一UA被反爬拦截。
内容的提问来源于stack exchange,提问作者user2882782
相关产品推荐
相关产品推荐

