You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python爬虫requests装饰器频繁报'too many calls'错误如何解决?

报错原因
  • 速率限制装饰器逻辑不完整:你仅使用了@limits装饰器限制调用次数,但没有配套处理触发的RateLimitException异常,现有代码遇到超限错误仅等待0.5秒就重试,远达不到速率重置的等待要求。
  • 函数内部的额外请求未纳入计数:@limits装饰器仅统计get_numbers函数的调用次数,但你在函数内部判断状态码非200时,额外发起了2次未被装饰器计数的requests.get请求,实际请求量远高于你设置的15次/15分钟的上限,直接触发站点的限流规则。
  • 速率设置与站点规则不匹配:你订阅pro-football-reference服务后,未对齐官方给出的速率限制要求,自行设置的15次/15分钟可能本身就超过了站点允许的请求频率。
  • 数据存储逻辑异常:当前仅在遇到报错时才将数据写入本地pickle文件,正常运行过程中不会落盘,若程序意外崩溃会导致已爬数据丢失,同时重复爬取已请求过的号码进一步增加无效请求量。
解决方案
  • 配套重试装饰器修正限流逻辑:将backoff重试装饰器和limits配合使用,统一管理请求和重试,避免手动发起未计数的额外请求,示例修改如下:
FIFTEEN_MINUTES = 900
# 参考官方限流值调低20%预留缓冲,可根据你订阅的服务规则调整具体数值
@on_exception(expo, RateLimitException, max_tries=5)
@limits(calls=10, period=FIFTEEN_MINUTES)
def get_numbers(jersey):
    url = f'https://www.pro-football-reference.com/players/uniform.cgi?number={jersey}'
    page = requests.get(url, timeout=10)
    time.sleep(10)
    if page.status_code != 200:
        # 非200状态码直接抛出异常,交给装饰器统一重试
        raise Exception(f"请求失败,状态码:{page.status_code}")
    html_content = page.text
    soup = BeautifulSoup(html_content, "lxml")
    return soup
  • 调整超限等待时长:删除现有代码中遇到"too many calls"仅等待0.5秒的逻辑,改为至少等待60秒再重试,或直接交给backoff的指数退避逻辑自动处理等待时长。
  • 优化数据落盘逻辑:每爬完3-5个号码就将数据写入pickle文件,不要仅在报错时落盘,减少重复请求。
  • 修正球员数据存储逻辑:当前代码遍历每个号码的球员列表时,会反复覆盖data[uni_num]的值,导致每个号码仅保留最后一个球员的信息,建议修改为每个号码对应一个列表,逐个追加球员数据:
# addplayerdata函数内修改存储逻辑
if uni_num not in data:
    data[uni_num] = []
for x in range(len(table_rows)):
    headings = []
    for th in table_rows[x]:
        headings.append(th.text.replace('\n', ' ').strip())
    player_dict = {"Player Name":headings[0],"Year From":headings[1],"Year To":headings[2],"AV":headings[3]}
    data[uni_num].append(player_dict)

内容的提问来源于stack exchange,提问作者Graham Waters

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 10:12:01