先日、ブログのトップページにGitHubの草を表示してみたという記事をあげました。
GitHubの草(コントリビューション)は日々の活動が可視化されるので、個人的にはとても良い仕組みだと思っています。しかし、週末くらいしか家でコードを書かない私のような人にとっては、土日ばかりに草が生えて残りはスカスカという悲しい感じに(´・ω・)
そこで、コントリビューションを週単位でまとめて表示する仕組みがあればよいのでは!ということで作ってみることにしました。
どこからデータを取ってくるか?
コントリビューションのデータは、GitHubが公開しているAPIを使えば取得可能です。しかし、サポートしているのが公開リポジトリに対するコントリビューションのみらしく、プライベートでひっそりと開発している人間にはあまり嬉しくありません。
そこで代替として、GitHubのページからデータを拾い上げて集計することにしました。
Pythonで実装してみる
軽く調べたところ、データの抽出にはPythonのBeautifulSoup
というライブラリを使うと楽とのこと。肝心のページの取得にはurllib
、グラフ描画はPillow
というライブラリでできることも分かったので、全てPythonで完結できそうです。
ページの取得
ページの取得にはurllib
のrequest
モジュールを使います。指定したURLから取ってくるだけであれば、こんな簡単に実装できます。
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
にコントリビューションの数が入っています。
試しに、各日付のコントリビューション数を表示するプログラムを書くとこんな感じになります。
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
2022/12/10追記
Herokuが無料プランを終了したため、weeklyGrassの稼働場所をHerokuからこのブログを動かしているサーバーに移動しました。Herokuは色々遊べたので良かったのですが残念ですね…(涙
2021/2/23追記
GitHubの仕様が変わったらしく、コントリビューションデータの取得にしばらく失敗していました…。ちゃんと直したのでいまは取得できるはず。スクレイピングはこういうのが辛いですね笑。
ではでは