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

如何通过GitHub API检索关键词对应超1000条的全部commits

超1000条GitHub commit搜索结果获取方案

GitHub网页端和Search Commits API确实对单次查询做了1000条返回的硬限制,直接翻页最多只能拿到前1000条结果,通过时间分片拆分查询范围的方式可以绕开这个限制,拿到全量匹配结果。

核心原理

1000条上限仅对单次生效的查询条件有效,只要把大的查询范围拆成多个小范围查询,保证每个小范围的匹配结果数不超过1000,最后把所有小范围的结果合并去重,就能拿到全部匹配数据。

操作步骤

  • 前置准备:生成GitHub个人访问令牌(PAT)用于接口认证,未认证状态下接口请求限额极低,认证后每小时可发起5000次请求,完全覆盖分片查询的需求。调用Search Commits接口时需要在请求头携带Accept: application/vnd.github.cloak-preview+json,否则无法正常返回commit搜索结果。
  • 初始范围统计:以关键词"data analysis"为例,先以GitHub首个commit上线时间2008-04-01为起始点、当前日期为结束点,拼接查询条件"data analysis" committer-date:2008-04-01..[当前日期],调用接口获取这个大时间范围下的总匹配条数。
  • 递归拆分时间区间:如果某个时间区间的总匹配条数大于1000,就把这个区间对半拆成两个连续的子区间,分别统计两个子区间的匹配数;如果子区间匹配数仍然超过1000就继续对半拆分,直到所有子区间的匹配结果数都≤1000为止。
  • 全量拉取合并:遍历所有拆分好的时间子区间,对每个区间做分页拉取,单页最大可设置100条结果,逐页翻到无新数据为止。最后对所有拉取到的commit按commit ID去重,避免时间边界处的commit被相邻区间重复收录,就能得到超过1000条的全量匹配结果。

避坑提示

  • 时间筛选优先使用committer-date字段,和GitHub网页端commit搜索的默认筛选逻辑一致,不要用author-date,否则会出现结果和网页端不匹配、漏数的问题。
  • 不要用固定时间粒度(比如每月、每季度一个区间)硬拆分,遇到关键词匹配密度高的时间段,固定粒度的区间仍然可能超过1000条上限触发限制,递归对半拆分的方式适配性最强,不管关键词热度多高都能拆到符合要求的粒度。
  • 接口请求要做限流重试,触发限流时可以根据响应头里的X-RateLimit-Reset字段等待限流重置后再发请求,避免被临时封禁。
  • 如果本身需要附加筛选条件(比如限定编程语言、所属组织、仓库星级等),可以直接把条件拼到查询参数里,能有效缩小单次查询的结果集大小,减少拆分的区间数量,降低请求次数。

核心逻辑参考代码

import requests
from datetime import datetime, timedelta

# 替换为自己的GitHub个人访问令牌
GITHUB_TOKEN = "your_personal_access_token"
REQ_HEADERS = {
    "Accept": "application/vnd.github.cloak-preview+json",
    "Authorization": f"token {GITHUB_TOKEN}"
}
SEARCH_KEYWORD = '"data analysis"'

def get_range_total(start_date: str, end_date: str) -> int:
    """获取指定时间范围内的匹配commit总数"""
    query = f"{SEARCH_KEYWORD} committer-date:{start_date}..{end_date}"
    resp = requests.get(
        "https://api.github.com/search/commits",
        headers=REQ_HEADERS,
        params={"q": query, "per_page": 1}
    )
    resp.raise_for_status()
    return resp.json()["total_count"]

def split_valid_range(start: str, end: str, slice_pool: list):
    """递归拆分出所有匹配数≤1000的时间区间"""
    total = get_range_total(start, end)
    if total <= 1000:
        slice_pool.append((start, end))
        return
    # 时间对半拆分
    start_dt = datetime.strptime(start, "%Y-%m-%d")
    end_dt = datetime.strptime(end, "%Y-%m-%d")
    mid_dt = start_dt + (end_dt - start_dt) / 2
    mid_str = mid_dt.strftime("%Y-%m-%d")
    mid_next_str = (mid_dt + timedelta(days=1)).strftime("%Y-%m-%d")
    split_valid_range(start, mid_str, slice_pool)
    split_valid_range(mid_next_str, end, slice_pool)

if __name__ == "__main__":
    # 生成所有合法查询分片
    valid_slices = []
    split_valid_range(
        "2008-04-01",
        datetime.now().strftime("%Y-%m-%d"),
        valid_slices
    )
    # 后续遍历valid_slices中的每个时间区间,分页拉取所有commits即可

内容的提问来源于stack exchange,提问作者Domin D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 01:04:07