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

如何通过等待重试正确处理GitHub API速率限制问题

问题原因
  • 你在for循环内手动修改循环变量i的操作完全不会生效:Python的for i in range(x)执行逻辑是由迭代器按固定顺序依次给i赋值,每轮循环结束后迭代器会自动取出下一个序列值覆盖i,你在异常分支里写i = i-1只能临时改变当前轮次的i值,完全不会影响下一轮迭代的页码取值,所以才会出现i从12直接跳到13、一直不重试失败页码的情况。
  • 固定5秒的等待时长不符合GitHub API的限流规则:GitHub搜索接口的限流周期是1分钟,认证用户每分钟最多发起30次搜索请求,触发限流后仅等待5秒远达不到限流重置的时间要求,会反复触发限流异常。
  • 宽泛的异常捕获没有区分错误类型:你没有先判断HTTP响应状态码就直接解析JSON取items字段,不管是限流、网络波动、接口返回格式错误都会进入异常分支,无法针对性处理限流场景。
修复方案
  1. 改用while循环控制页码,只有当前页请求成功、数据全部写入结果列表后,再把页码+1,失败时不修改页码,直接重试当前页。
  2. 请求后先判断响应状态码,触发限流时优先读取响应头里的X-RateLimit-Reset字段,计算距离限流重置的剩余等待时间,不用固定写死等待时长;单页设置重试次数上限,避免出现死循环。
  3. 不要使用无差别的裸except,针对性捕获请求相关异常,方便排查问题。

修复后的参考代码:

import time
import requests
from datetime import datetime

repositories = []
current_page = 1  # GitHub分页page从1开始计数
max_page = 33
max_retry = 5  # 单页最大重试次数,避免死循环

# 替换成你自己携带授权令牌的请求头
headers = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/vnd.github.v3+json"
}

while current_page <= max_page:
    retry_count = 0
    page_success = False
    while retry_count < max_retry:
        try:
            url = f"https://api.github.com/search/repositories?q=language:java&sort=forks&order=desc&per_page=30&page={current_page}"
            response = requests.get(url=url, headers=headers)
            # 优先处理限流场景
            if response.status_code in [403, 429]:
                reset_timestamp = int(response.headers.get("X-RateLimit-Reset", time.time() + 60))
                wait_seconds = reset_timestamp - int(time.time()) + 2  # 多等2秒做时间容错
                print(f"触发接口限流,等待{wait_seconds}秒后重试当前页")
                time.sleep(max(wait_seconds, 1))
                retry_count += 1
                continue
            # 其他HTTP错误直接抛出
            response.raise_for_status()
            resp_json = response.json()
            # 写入当前页数据
            for repository in resp_json["items"]:
                dt_string = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
                repositories.append({
                    "name": repository["full_name"],
                    "link": repository["html_url"],
                    "date": dt_string
                })
            print(f"第{current_page}页拉取成功,当前累计获取{len(repositories)}条仓库数据")
            page_success = True
            break
        except Exception as e:
            print(f"请求第{current_page}页出错: {str(e)},10秒后重试")
            time.sleep(10)
            retry_count += 1
    if page_success:
        current_page += 1
    else:
        print(f"第{current_page}页重试次数耗尽,终止拉取")
        break

print("Repositories taken.")

补充说明:

  • GitHub搜索接口默认单页最多返回100条结果,你可以把请求参数里的per_page设为100,总页数降到10页以内,能大幅降低触发限流的概率。
  • 你原代码从page=0开始请求,会和page=1返回重复的第一页数据,实际拉取的有效数据量会少于预期。

内容的提问来源于stack exchange,提问作者Basak Balci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:15:45