Python中如何爬取GitHub上所有merged的PR并展示在README中
面试的时候经常被问到参与过什么开源项目,每次都是找几个然后发链接过去,虽然面试官直接可以从 pull request 页面直接搜,但是还是比较麻烦。所以自己写了个工具,能爬取所有被 merged 的 PR,然后写 README.md 并自动 Push 到 Github 上的仓库。
很久没有用 python 了,语法都快忘的差不多了,代码写的不是很好,后面自己慢慢改,觉得有用的同学可以 fork 过去直接使用,可以提提意见,主要是展示 PR 信息那一栏,没有想出好看布局。
https://github.com/Leviathan1995/MyContribution
欢迎大家提 Issue, star
Python中如何爬取GitHub上所有merged的PR并展示在README中
7 回复
https://github.com/CodeFalling/MyContribution
晒一个,不知不觉蹭了好多 PR,这个小工具挺有用的,给你点个赞
import requests
import base64
from datetime import datetime
def fetch_merged_prs(repo_owner, repo_name, token=None):
"""
获取GitHub仓库所有merged的PR
"""
prs = []
page = 1
headers = {'Accept': 'application/vnd.github.v3+json'}
if token:
headers['Authorization'] = f'token {token}'
while True:
url = f'https://api.github.com/repos/{repo_owner}/{repo_name}/pulls'
params = {
'state': 'closed',
'per_page': 100,
'page': page
}
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
raise Exception(f"API请求失败: {response.status_code}")
data = response.json()
if not data:
break
for pr in data:
if pr['merged_at']: # 只收集已合并的PR
prs.append({
'number': pr['number'],
'title': pr['title'],
'user': pr['user']['login'],
'merged_at': pr['merged_at'],
'html_url': pr['html_url']
})
# 检查是否还有下一页
if 'next' not in response.links:
break
page += 1
# 按合并时间倒序排列
return sorted(prs, key=lambda x: x['merged_at'], reverse=True)
def generate_pr_markdown(prs):
"""
生成PR列表的Markdown格式
"""
markdown = "## 📌 已合并的Pull Requests\n\n"
markdown += "| PR编号 | 标题 | 贡献者 | 合并时间 |\n"
markdown += "|--------|------|--------|----------|\n"
for pr in prs[:50]: # 只显示最近的50个
date = datetime.strptime(pr['merged_at'], '%Y-%m-%dT%H:%M:%SZ')
formatted_date = date.strftime('%Y-%m-%d %H:%M')
markdown += f"| [#{pr['number']}]({pr['html_url']}) | {pr['title']} | @{pr['user']} | {formatted_date} |\n"
if len(prs) > 50:
markdown += f"\n> 显示最近50个PR,共{len(prs)}个已合并PR\n"
return markdown
def update_readme(repo_owner, repo_name, token, pr_markdown):
"""
更新README文件
"""
# 1. 获取当前README内容
readme_url = f'https://api.github.com/repos/{repo_owner}/{repo_name}/contents/README.md'
headers = {'Accept': 'application/vnd.github.v3+json'}
if token:
headers['Authorization'] = f'token {token}'
response = requests.get(readme_url, headers=headers)
if response.status_code == 404:
# README不存在,创建新文件
content = ""
sha = None
elif response.status_code == 200:
# 解码现有内容
data = response.json()
content = base64.b64decode(data['content']).decode('utf-8')
sha = data['sha']
else:
raise Exception(f"获取README失败: {response.status_code}")
# 2. 替换或添加PR部分
start_marker = "## 📌 已合并的Pull Requests"
end_marker = "## " # 下一个标题开始
if start_marker in content:
# 找到现有PR部分的位置
start_idx = content.find(start_marker)
next_section = content.find(end_marker, start_idx + len(start_marker))
if next_section != -1:
# 替换现有内容
new_content = content[:start_idx] + pr_markdown + content[next_section:]
else:
# PR部分是最后一部分
new_content = content[:start_idx] + pr_markdown
else:
# 在文件末尾添加PR部分
new_content = content.rstrip() + "\n\n" + pr_markdown
# 3. 更新README
update_data = {
'message': '更新已合并PR列表',
'content': base64.b64encode(new_content.encode('utf-8')).decode('utf-8')
}
if sha:
update_data['sha'] = sha
update_response = requests.put(readme_url, headers=headers, json=update_data)
if update_response.status_code in [200, 201]:
print("README更新成功!")
else:
print(f"更新失败: {update_response.status_code}")
def main():
# 配置信息
REPO_OWNER = "your_username"
REPO_NAME = "your_repository"
GITHUB_TOKEN = "your_github_token" # 需要repo权限
try:
# 1. 获取已合并的PR
print("正在获取已合并的PR...")
prs = fetch_merged_prs(REPO_OWNER, REPO_NAME, GITHUB_TOKEN)
print(f"找到 {len(prs)} 个已合并的PR")
# 2. 生成Markdown
markdown = generate_pr_markdown(prs)
# 3. 更新README
update_readme(REPO_OWNER, REPO_NAME, GITHUB_TOKEN, markdown)
except Exception as e:
print(f"执行出错: {e}")
if __name__ == "__main__":
main()
使用说明:
-
获取GitHub Token:
- 访问 https://github.com/settings/tokens
- 生成新token,勾选
repo权限
-
修改配置:
- 替换
REPO_OWNER为仓库所有者 - 替换
REPO_NAME为仓库名 - 替换
GITHUB_TOKEN为你的token
- 替换
-
运行脚本:
python github_pr_tracker.py
脚本功能:
- 自动获取所有已合并的PR
- 按合并时间倒序排列
- 生成美观的Markdown表格
- 自动更新README文件
- 处理分页(支持大量PR)
注意事项:
- 首次运行会在README末尾添加PR部分
- 后续运行会自动更新现有PR列表
- 默认显示最近50个PR,可修改
generate_pr_markdown中的数量
总结: 用GitHub API获取PR数据,然后自动更新README。
诶我是不是在群里见过你,有没有兴趣来阿里 
#3 第一次 push 的时候我把密码输错了(你永远不知道用户会干什么系列)
我不知道你是哪届的,2018 届的秋招应该还没开始
我是 17 届的,和你一届吧。我也记得你
邮箱联系吧,github 上有我邮箱。

