如何用GitHub API v3及Python标准库获取指定时段分支的活跃用户及提交数
解决GitHub API获取指定分支、时间段活跃用户的问题
我来帮你搞定这个问题——你碰到的422错误是因为请求头设置错了,而且search/commits其实完全支持指定分支和时间段,只是你没用到正确的查询参数。下面一步步来解决:
1. 先修复HTTP 422错误
你的代码里请求头的写法搞反了,应该把Accept作为头名称,application/vnd.github.cloak-preview作为头的值,而不是反过来。正确的写法是:
q.add_header('Accept', 'application/vnd.github.cloak-preview')
2. 如何指定分支和时间段
search/commits的查询参数可以通过q字符串叠加多个条件,用+分隔:
- 指定分支:添加
branch:你的分支名,比如branch:main - 指定时间段:用
committer-date:起始日期..结束日期,比如committer-date:2024-01-01..2024-06-01,也可以用>=/<=来限定单边范围
比如查询octocat/Spoon-Knife仓库main分支在2024年上半年的提交,完整的q参数是:repo:octocat/Spoon-Knife+branch:main+committer-date:2024-01-01..2024-06-01
3. 完整Python实现(基于标准库)
下面的代码会完成这些事:
- 遍历所有分页的提交结果(API每页最多返回100条)
- 统计每个用户的提交次数
- 按提交次数降序排序,取前30位活跃用户
import urllib.request import json from collections import defaultdict def get_top_active_users(repo_owner, repo_name, branch, start_date, end_date, top_n=30): base_url = "https://api.github.com/search/commits" # 构建查询参数 query = f"repo:{repo_owner}/{repo_name}+branch:{branch}+committer-date:{start_date}..{end_date}" url = f"{base_url}?q={query}&per_page=100" # 每页取最大100条 commit_counts = defaultdict(int) page = 1 while url: try: req = urllib.request.Request(url) # 设置正确的Accept头 req.add_header('Accept', 'application/vnd.github.cloak-preview') # 有GitHub令牌的话可以加上,提升速率限制:req.add_header('Authorization', 'token 你的令牌') response = urllib.request.urlopen(req) data = json.loads(response.read().decode('utf-8')) # 统计每个用户的提交数 for item in data['items']: author_login = item['author']['login'] if item['author'] else 'unknown' commit_counts[author_login] += 1 # 处理分页:获取下一页的URL links = response.getheader('Link') url = None if links: for link in links.split(','): if 'rel="next"' in link: url = link.split(';')[0].strip('<>') page += 1 except urllib.error.HTTPError as e: print(f"HTTP错误 {e.code}: {e.read().decode('utf-8')}") break # 按提交次数降序排序,取前top_n sorted_users = sorted(commit_counts.items(), key=lambda x: x[1], reverse=True)[:top_n] return sorted_users # 示例调用 if __name__ == "__main__": top_users = get_top_active_users( repo_owner="octocat", repo_name="Spoon-Knife", branch="main", start_date="2024-01-01", end_date="2024-06-01" ) print("Top 30活跃用户及提交次数:") for idx, (login, count) in enumerate(top_users, 1): print(f"{idx}. {login}: {count}次提交")
关键注意点
- 速率限制:未认证的GitHub API请求每小时最多60次,如果你需要更高的调用额度,建议添加GitHub个人访问令牌(在请求头里加
Authorization: token 你的令牌),认证后每小时最多5000次。 - 无关联用户的提交:有些提交可能没关联GitHub账号(比如用邮箱提交但未绑定账号),代码里会标记为
unknown,你可以根据需求调整这部分逻辑。 - 结果上限:
search/commits最多返回1000条结果,如果目标时间段内提交超过1000条,这个方法可能无法统计全部(GitHub的限制)。这种情况下可以改用GET /repos/{owner}/{repo}/commits接口遍历分支的所有提交,虽然分页处理更繁琐,但没有1000条的限制。
内容的提问来源于stack exchange,提问作者 Sergisson
相关产品推荐
相关产品推荐

