GitHubリポジトリのスター数順にOSSをソートしランキング化する方法を紹介します。
成果物
検索スクリプト
以下にスクリプトを公開していますのでご活用ください。
後述するpage
パラメタをインクリメントしながら検索しますので便利です。
ランキング
本記事で紹介している方法で作成したGo言語のWebフレームワークランキングです。
ランキング作成方法
リポジトリをスター数順に検索&ソートする
GitHub REST API v3 の Search APIを利用します。
APIエンドポイント
https://api.github.com/search/repositories
APIパラメタ
詳細はsearch/#parametersをご参照下さい。
パラメタ | 設定値 | 設定例 |
---|---|---|
q | 以下を含むクエリ検索キーワード(要URIエンコード) in language stars
|
web+framework |
in | 検索対象name : リポジトリ名description : 概要readme : README.md |
name,description,readme |
language | 言語 | go |
stars | スター数の条件 | >=1000 |
sort | ソートする項目 | start |
order | ソート順序 | desc |
per_page | 1ページあたりのitem数 | 10 |
page | ページ番号(1始まり) | 1 |
per_page
とpage
についてはPaginationをご参照下さい。
page
パラメタを適宜インクリメントしながら複数回検索する必要があります。
検索コマンド
スター数1000以上のGo言語のリポジトリを対象にweb framework
をキーワードに検索するコマンドの例です。
LANGUAGE=go
KEYWORD=web+framework
STAR=1000
USER=your_username
PASS=your_password
page=1
curl -u ${USER}:${PASS} "https://api.github.com/search/repositories?q=${KEYWORD}+in:name,description,readme+language:${LANGUAGE}+stars:>=${STAR}&sort=stars&order=desc&per_page=10&page=${page}"
認証は必須ではありませんが制限(rate limit)にひっかかりにくいので実施してます。
上記例はBASIC認証ですがOAuth2認証にしたい方は以下記事を参照下さい。
GitHub API を 叩く
検索結果
total_count
は全リポジトリ数です。
items
はリポジトリの配列で要素数は最大でper_page
です。
stargazers_count
がスター数で降順にソートされています。
{
"total_count": 61,
"incomplete_results": false,
"items": [
{
"id": 21540759,
"node_id": "MDEwOlJlcG9zaXRvcnkyMTU0MDc1OQ==",
"name": "awesome-go",
"full_name": "avelino/awesome-go",
"private": false,
"owner": {
"login": "avelino",
"id": 31996,
"node_id": "MDQ6VXNlcjMxOTk2",
"avatar_url": "https://avatars2.githubusercontent.com/u/31996?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/avelino",
"html_url": "https://github.com/avelino",
"followers_url": "https://api.github.com/users/avelino/followers",
"following_url": "https://api.github.com/users/avelino/following{/other_user}",
"gists_url": "https://api.github.com/users/avelino/gists{/gist_id}",
"starred_url": "https://api.github.com/users/avelino/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/avelino/subscriptions",
"organizations_url": "https://api.github.com/users/avelino/orgs",
"repos_url": "https://api.github.com/users/avelino/repos",
"events_url": "https://api.github.com/users/avelino/events{/privacy}",
"received_events_url": "https://api.github.com/users/avelino/received_events",
"type": "User",
"site_admin": false
},
"html_url": "https://github.com/avelino/awesome-go",
"description": "A curated list of awesome Go frameworks, libraries and software",
"fork": false,
"url": "https://api.github.com/repos/avelino/awesome-go",
"forks_url": "https://api.github.com/repos/avelino/awesome-go/forks",
"keys_url": "https://api.github.com/repos/avelino/awesome-go/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/avelino/awesome-go/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/avelino/awesome-go/teams",
"hooks_url": "https://api.github.com/repos/avelino/awesome-go/hooks",
"issue_events_url": "https://api.github.com/repos/avelino/awesome-go/issues/events{/number}",
"events_url": "https://api.github.com/repos/avelino/awesome-go/events",
"assignees_url": "https://api.github.com/repos/avelino/awesome-go/assignees{/user}",
"branches_url": "https://api.github.com/repos/avelino/awesome-go/branches{/branch}",
"tags_url": "https://api.github.com/repos/avelino/awesome-go/tags",
"blobs_url": "https://api.github.com/repos/avelino/awesome-go/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/avelino/awesome-go/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/avelino/awesome-go/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/avelino/awesome-go/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/avelino/awesome-go/statuses/{sha}",
"languages_url": "https://api.github.com/repos/avelino/awesome-go/languages",
"stargazers_url": "https://api.github.com/repos/avelino/awesome-go/stargazers",
"contributors_url": "https://api.github.com/repos/avelino/awesome-go/contributors",
"subscribers_url": "https://api.github.com/repos/avelino/awesome-go/subscribers",
"subscription_url": "https://api.github.com/repos/avelino/awesome-go/subscription",
"commits_url": "https://api.github.com/repos/avelino/awesome-go/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/avelino/awesome-go/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/avelino/awesome-go/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/avelino/awesome-go/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/avelino/awesome-go/contents/{+path}",
"compare_url": "https://api.github.com/repos/avelino/awesome-go/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/avelino/awesome-go/merges",
"archive_url": "https://api.github.com/repos/avelino/awesome-go/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/avelino/awesome-go/downloads",
"issues_url": "https://api.github.com/repos/avelino/awesome-go/issues{/number}",
"pulls_url": "https://api.github.com/repos/avelino/awesome-go/pulls{/number}",
"milestones_url": "https://api.github.com/repos/avelino/awesome-go/milestones{/number}",
"notifications_url": "https://api.github.com/repos/avelino/awesome-go/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/avelino/awesome-go/labels{/name}",
"releases_url": "https://api.github.com/repos/avelino/awesome-go/releases{/id}",
"deployments_url": "https://api.github.com/repos/avelino/awesome-go/deployments",
"created_at": "2014-07-06T13:42:15Z",
"updated_at": "2019-01-05T14:58:22Z",
"pushed_at": "2019-01-05T09:41:48Z",
"git_url": "git://github.com/avelino/awesome-go.git",
"ssh_url": "git@github.com:avelino/awesome-go.git",
"clone_url": "https://github.com/avelino/awesome-go.git",
"svn_url": "https://github.com/avelino/awesome-go",
"homepage": "https://awesome-go.com/",
"size": 4851,
"stargazers_count": 38695,
"watchers_count": 38695,
"language": "Go",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": false,
"has_pages": true,
"forks_count": 5035,
"mirror_url": null,
"archived": false,
"open_issues_count": 31,
"license": {
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZTEz"
},
"forks": 5035,
"open_issues": 31,
"watchers": 38695,
"default_branch": "master",
"permissions": {
"admin": false,
"push": false,
"pull": true
},
"score": 94.155464
},
( 略 : )
{
( 略 : )
}
]
}
検索結果を整形
ランキングとして表示するには項目が多すぎますので見やすいフォーマットに加工します。
CSV ( or Json ) にする
以下項目を抽出します。
リポジトリ名,スター数,リポジトリURL,概要
jq
コマンドでCSV形式に加工する例です。
なお、| @csv
を削除するとjson形式になります。
curl -u ${USER}:${PASS} "https://api.github.com/search/repositories?q=${KEYWORD}+in:name,description,readme+language:${LANGUAGE}+stars:>=${STAR}&sort=stars&order=desc&per_page=10&page=${page}" | jq -r ".items[] | [.full_name , .stargazers_count, .html_url, .description] | @csv"
整形結果
1行1リポジトリとなりすっきりしました。
"avelino/awesome-go",38695,"https://github.com/avelino/awesome-go","A curated list of awesome Go frameworks, libraries and software"
"gin-gonic/gin",23408,"https://github.com/gin-gonic/gin","Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin."
"astaxie/beego",18465,"https://github.com/astaxie/beego","beego is an open-source, high-performance web framework for the Go programming language."
"kataras/iris",13285,"https://github.com/kataras/iris","The fastest backend community-driven web framework on (THIS) Earth. HTTP/2, MVC and more. Can your favourite web framework do that? 👉 http://bit.ly/iriscandothat1 or even http://bit.ly/iriscandothat2"
"openfaas/faas",12576,"https://github.com/openfaas/faas","OpenFaaS - Serverless Functions Made Simple"
"labstack/echo",12566,"https://github.com/labstack/echo","High performance, minimalist Go web framework"
"go-kit/kit",12312,"https://github.com/go-kit/kit","A standard library for microservices."
"revel/revel",10638,"https://github.com/revel/revel","A high productivity, full-stack web framework for the Go language."
"go-martini/martini",10411,"https://github.com/go-martini/martini","Classy web framework for Go"
"boltdb/bolt",9314,"https://github.com/boltdb/bolt","An embedded key/value database for Go."
ノイズの除去
最終的なランキングデータとするには、ノイズ(検索キーワードは含まれているが目的に沿わない検索結果)の除去が必要です。
ノイズかどうか判断するにはdescription
やREADME.md
(特に序章の紹介文)を読むのが良いです。
やはり最終的には人力が必要になりますが、ここまでの作業でスター数が多い順に絞り込まれていますので、
上から順に精査しノイズを除去していくと後戻りなくランキングトップXX(トップ10など)が出揃います。
Markdownにする
CSV To Markdown Table GeneratorのようなサイトでCSVをMarkdownのテーブルに変換できます。
Qiita等に投稿するのに便利です。
まとめ
GitHubリポジトリのスター数順にOSSをランキングする方法と成果物を紹介しました。
スター数以外にもコミュニティの活発度、機能性や性能など、OSSを選定するための基準はたくさんあります。
開発に適したOSSを選定するための指標の1つとして本記事のランキング作成方法が手助けになりましたら幸いです。