优先使用 github 官方 rest api 获取公开仓库数据,需携带 authorization header 避免限流;推荐 pygithub 封装以提升可读性与容错性,避免 html 爬取因其不稳定、易失效且违反 robots.txt。

GitHub 的公开仓库数据,优先走官方 API,而不是硬爬 HTML 页面。这是最稳定、最合规、也最容易落地的方式 —— 除非你明确需要 API 不提供的字段(比如某个页面上动态渲染的“最近活跃贡献者头像”),否则别碰网页解析。
用 requests 调 GitHub REST API 是最直接的方案
GitHub 官方 API 返回标准 JSON,结构清晰,字段完整,star_count、language、updated_at、description 全都有,不用自己猜 selector。
常见错误现象:403 Forbidden 或返回空 items 列表 —— 这几乎全是没带 Authorization header 导致的限流(未认证用户仅 50 次/小时)。
- 必须加请求头:
headers = {"Authorization": "token YOUR_PERSONAL_ACCESS_TOKEN"} - 搜索接口示例:
https://api.github.com/search/repositories?q=language:python&sort=stars&per_page=30&page=1 -
per_page最大为 30,翻页靠page参数,不是offset - 注意响应里
Linkheader 中的rel="next",它比手动递增page更可靠(尤其跨页时有新仓库插入)
PyGithub 封装能省掉 70% 的胶水代码
如果你要批量读取仓库详情(比如每个 full_name 对应的 topics、license、forks_count),手写 requests 会很快变得冗长。PyGithub 把这些封装成对象方法,可读性高、容错强。
容易踩的坑:Github().get_repo("owner/name") 会触发一次额外 API 调用获取完整信息,但如果你只调了 search_repositories(),返回的 Repository 对象默认是“轻量级”的 —— 部分字段(如 topics)为空,得显式调 repo.pull_request() 或 repo.edit() 以外的任意方法触发懒加载(实际是再发一次 GET)。
- 初始化时务必传 token:
g = Github("your_token_here") - 搜索后遍历结果前,先用
repo.raw_data.keys()看当前对象已加载哪些字段 - 避免在循环里反复创建
Github实例,复用一个实例即可
别碰 HTML 爬取,除非你真清楚代价
网页结构随时可能变:div.repo-list-item 下一代可能改成 article.hx-2;a[href$='stargazers'] 可能被 JS 动态注入,requests 拿不到;更别说 robots.txt 明确禁止部分路径(如 /search 的某些参数组合)。
性能与兼容性影响明显:HTML 解析比 JSON 解析慢 3–5 倍;BeautifulSoup 在不同 parser(html.parser vs lxml)下对破损标签行为不一致;且 GitHub 会逐步加强反爬(如要求 Cookie + JavaScript challenge)。
- 如果非得用,至少加
time.sleep(2)控制频率,别用random.uniform(0.8, 1.5)自欺欺人 - 永远检查
response.status_code == 200和len(soup.select(...)) > 0,别假设 selector 一定存在 - 不要依赖页面上“人眼可见”的文字顺序 —— 屏幕阅读器 DOM 顺序、JS 渲染顺序、服务端 SSR 顺序可能全不同
updated_at 是 UTC 时间,但没存时区标识;或者某次请求漏了 license 字段,后续分析时才发现缺失不可补。这些细节,API 能帮你兜底,HTML 爬取只能靠你自己一条条校验。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











