A PHP GitHub Trending Crawler

GitHub: github_trending_crawler

简介

由于 GitHub 官方提供的 API 并不包含 GitHub Trending 相关的接口,而作为好学开发者,我们都会去关注 Trending 趋势,以获取最近 GitHub 上相关编程语言有哪些优秀项目和哪些开发者最火。另外,我们在开发第三方 GitHub App 时,通常也需要展示 Trending 数据,如果直接在客户端抓取解析,吃力不讨好,且国内访问速度较慢,此时就需要服务端提供相关接口来解决问题。

本仓库提供了一个 PHP 小爬虫,用于在服务端定时抓取解析 GitHub Trending 数据并缓存,以提供给客户端快速(秒级)的查询接口。它可以分别以天(Daily)、周(Weekly)、月(Monthly)三个维度抓取各种编程语言下最受关注的 RepositoriesDevelopers

说明

这个小爬虫的核心代码主要是 crawler 文件夹下的 simple_html_dom.phpgithub_trending_crawler.php 两个文件。

simple_html_dom.php

此文件来自开源库 PHP Simple HTML DOM Parser,它提供了一个简单易用单,功能强大的 HTML DOM 解析方法,便于我们用 PHP 抓取网页的 HTML 并进行分析。

github_trending_crawler.php

此文件主要用于抓取解析 GitHub Trending 数据,包含以下方法:

  • gt_get_html_dom()

此方法需要传入一个 url 参数,用于获取指定 url 下的 HTML,并返回一个 simple_html_dom 对象,方便后续解析 HTML 中不同标签里的数据。

  • gt_get_top_languages()

此方法用于获取 GitHub Trending 页面右侧推荐的目前较流行的编程语言(注:登录状态下每个人看到的结果可能不同,此方法是在未登录下抓取的),返回一个 languages 数组,数组中的每一项包含 nameid 两个字段,大致如下:

1
{"languages":[{"name":"C++","id":"c++"},{"name":"PHP","id":"php"}, ... ]}
  • gt_get_all_languages()

此方法用于获取 GitHub 所有的编程语言,同样返回一个 languages 数组,结构与上述类似。

  • gt_get_repositories()

此方法接收两个参数 langsince,其中 lang 的取值来自上述 languages 中返回的 idsince 的取值包括 dailyweeklymonthly,它用于获取指定时间维度下,某一编程语言最受关注的开源项目,返回一个 repositories 数组,大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"repositories": [{
"author": "airbnb",
"title": "lottie-ios",
"url": "https://github.com/airbnb/lottie-ios",
"description": "An iOS library to natively render After Effects vector animations",
"language": "Objective-C",
"stars": "13,084",
"forks": "1,683",
"newStars": "25 stars today",
"contributors": [{
"id": "buba447",
"avatar": "https://avatars1.githubusercontent.com/u/1163980"
}, {
"id": "welshm",
"avatar": "https://avatars0.githubusercontent.com/u/3903024"
}, {
"id": "valeriyvan",
"avatar": "https://avatars0.githubusercontent.com/u/1630974"
}, {
"id": "hansemannn",
"avatar": "https://avatars3.githubusercontent.com/u/10667698"
}, {
"id": "fnazrala",
"avatar": "https://avatars2.githubusercontent.com/u/2164816"
}]
},

...

]}
  • gt_get_developers()

此方法同样接收两个参数 langsince,取值与 gt_get_repositories() 方法类似,它用于获取指定时间维度下,某一编程语言最受欢迎的开发者,返回一个 developers 数组,大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"developers": [{
"url": "https://github.com\/facebook",
"avatar": "https://avatars2.githubusercontent.com/u/69631",
"name": "Facebook",
"id": "facebook",
"repository": {
"url": "https://github.com/facebook/Shimmer",
"title": "Shimmer",
"desp": "An easy way to add a simple, shimmering effect to any view in an iOS app."
}
},

...

]}

注意:如果 GitHub Trending 访问失败、超时,或者某一维度下页面没有数据,或者解析异常,上述方法都会返回 null而且如果以后 GitHub Trending 页面的 HTML 结构发生变化,上述方法的解析逻辑也要做相应的修改。

使用示例

为了方便大家正确使用 github_trending_crawler.php,我写了一个 example.php 示例脚本,
crawler 文件夹和 example.php 文件放到你的 Web 目录下,并访问以下 URL 路径,即可获得相应结果,具体的逻辑详见 example.php 文件,不再赘述(在 PHP 5.6 测试通过)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 默认获取今日所有编程语言下开源项目的 Trending 数据
https://path/to/example.php

// 获取今日 Swift 语言下开源项目的 Trending 数据
https://path/to/example.php?lang=swift&since=daily

// 获取本月 Swift 语言下开源项目的 Trending 数据
https://path/to/example.php?action=repositories&lang=swift&since=monthly

// 获取本周 Objective-C 语言下开发者的 Trending 数据
https://path/to/example.php?action=developers&lang=objective-c&since=weekly

// 获取最受关注的编程语言和所有的编程语言列表
https://path/to/example.php?action=top_languages
https://path/to/example.php?action=all_languages

其中,URLquery 请求参数的默认值如下:

  • lang: null // 默认获取全部语言的结果
  • since: daily // 默认获取今日的数据
  • action: repositories // 默认获取开源项目数据

当然,如果每次访问 example.php 脚本都去实时抓取一遍数据,显然是很耗时的,而且 GitHub Trending 页面的更新频率也不是很快,所以我们可以在服务端通过 Redis 把数据缓存下来,下次访问时如果缓存中有数据就直接返回,可以大大提高访问速度,详见 example_with_redis.php 文件。

另外,你可以在你的服务端开启一些 Crontab 定时任务,定时去抓取数据更新缓存,以便提供给客户端的接口可以快速响应。

注意,如果你的 PHP 脚本在运行过程中报如下错误:

1
file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version in /path/to/simple_html_dom.php on line 75.

那是因为 February 01, 2018 起,GitHub 限制 HTTPS 访问只能用 TLSv1.2,详见这里,所以你可能需要更新一下你服务端的 OpenSSL 版本。

测试接口

为了让大家能够更直观地感受上述小爬虫所带来的效果,我在我自己的服务器上部署了一套环境,大家可以直接访问以下示例 URL 获得相关结果:

// 默认获取今日所有编程语言下开源项目的 Trending 数据

https://app.kangzubin.com/trending/test

// 获取今日 Swift 语言下开源项目的 Trending 数据

https://app.kangzubin.com/trending/test?lang=swift&since=daily

// 获取本月 Swift 语言下开源项目的 Trending 数据

https://app.kangzubin.com/trending/test?action=repositories&lang=swift&since=monthly

// 获取本周 Objective-C 语言下开发者的 Trending 数据

https://app.kangzubin.com/trending/test?action=developers&lang=objective-c&since=weekly

// 获取最受关注的编程语言列表

https://app.kangzubin.com/trending/test?action=top_languages

// 获取所有的编程语言列表

https://app.kangzubin.com/trending/test?action=all_languages

重要说明:第一次访问上述接口获取相关数据时,如果缓存中有数据,就直接返回;如果缓存中没有数据,会实时抓取 GitHub Trending 页面数据进行解析并缓存,此时接口返回的速度回比较慢。另外,由于是测试用,所以数据一旦缓存后,我并没有去定时更新,所以上述测试接口有时候返回的数据可能是过时的。

!!!上述接口仅供大家体验,不建议在你的服务或 App 中直接使用,因为我可能会随时下线。

BY THE WAY

如果你问我写爬虫为什么采用 PHP 而不用 Python,那当然是因为 PHP 是… 😷

PHP is the best language in the world

图片来自《神秘的程序员们》

LICENSE

This repositorie is released under the MIT license. See LICENSE for details.