先日、ブログのトップページにGitHubの草を表示してみたという記事をあげました。
GitHubの草(コントリビューション)は日々の活動が可視化されるので、個人的にはとても良い仕組みだと思っています。しかし、週末くらいしか家でコードを書かない私のような人にとっては、土日ばかりに草が生えて残りはスカスカという悲しい感じに(´・ω・)
そこで、コントリビューションを週単位でまとめて表示する仕組みがあればよいのでは!ということで作ってみることにしました。
どこからデータを取ってくるか?
コントリビューションのデータは、GitHubが公開しているAPIを使えば取得可能です。しかし、サポートしているのが公開リポジトリに対するコントリビューションのみらしく、プライベートでひっそりと開発している人間にはあまり嬉しくありません。
そこで代替として、GitHubのページからデータを拾い上げて集計することにしました。
https://github.com/users/<UserID>/contributions
にアクセスすると以下のようなページが表示されます。UserID
は適宜ご自身のGitHubアカウント名に置き換えてください。このうち、上部にあるグラフにコントリビューション情報が埋め込まれているので、それを拾い集める形としました。
Pythonで実装してみる
軽く調べたところ、データの抽出にはPythonのBeautifulSoup
というライブラリを使うと楽とのこと。肝心のページの取得にはurllib
、グラフ描画はPillow
というライブラリでできることも分かったので、全てPythonで完結できそうです。
ページの取得
ページの取得にはurllib
のrequest
モジュールを使います。指定したURLから取ってくるだけであれば、こんな簡単に実装できます。
1 2 3 4 5 6 7 |
from urllib import request username = "corgi0901" url = "https://github.com/users/" + username + "/contributions" response = request.urlopen(url) |
データ抽出
続いて、取得したページから必要なデータを取り出します。上述したコード中のresponse
を引数に渡してBeautifulSoup
を初期化したあと、検索条件を指定すれば、該当する要素をかき集めることができます。
今回対象としているページでは、コントリビューション情報は「rect
かつclass
がday
」となっている要素です。そして、さらにその要素を紐解くと、data-date
に日付、data-count
にコントリビューションの数が入っています。
試しに、各日付のコントリビューション数を表示するプログラムを書くとこんな感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from urllib import request from bs4 import BeautifulSoup # ページを取得 username = "corgi0901" url = "https://github.com/users/" + username + "/contributions" response = request.urlopen(url) # BeautifulSoup初期化 soup = BeautifulSoup(response, "html.parser") response.close() # コントリビューション情報を抽出 contributions = soup.find_all("rect", class_="day") # 各日付毎にコントリビューション数を表示 for day in contributions: date = day.get("data-date") count = day.get("data-count") print(date, ":", count) |
実行結果はこんな感じです。過去1年分のコントリビューション数が取得できました。
2019-05-13 : 0
2019-05-14 : 0
2019-05-15 : 2
2019-05-16 : 0
~ 途中省略 ~
2020-05-07 : 7
2020-05-08 : 0
2020-05-09 : 0
2020-05-10 : 2
2020-05-11 : 0
グラフの描画
情報が取得できれば、あとはグラフを描画するだけです。Pillow
というライブラリを使えば、画像の描画からテキストの埋め込みまで行うことができます。
以下のドキュメントなどを参考にしながら実装しました。実際のコードは少しごちゃごちゃしちゃったので割愛します。
あれこれ試行錯誤した結果、最終的に以下のような画像を吐き出すことができました。週単位でコントリビューション数を集計した結果を棒グラフとして表示しています。
1週間単位の成果がグラフになるので、これなら「草を絶やさない」ことも簡単です。週に1度はコミットすれば草が生えます笑。せっかくなので、このブログのトップページにあるグラフもこれに置き換えました。
おまけ:サービス公開してみた
今回の目的は達成しましたが、昨今の諸事情で時間があったので、「Weekly Grass」という名前でWebサービス化してみることにしました。前からちょっと気になっていたFlaskでサーバーサイドを実装し、Herokuでデプロイしています。
それっぽい見た目にはなって個人的には満足です。無料アカウントで動かしているので、異常にアクセスが遅いときもありますし、飽きたら閉めるかもしれません。
もし興味のある方は今のうちに触ってみて下さいm(_ _)m
2021/2/23追記
GitHubの仕様が変わったらしく、コントリビューションデータの取得にしばらく失敗していました…。ちゃんと直したのでいまは取得できるはず。スクレイピングはこういうのが辛いですね笑。
ではでは