Github Grassを取得するテスト

ちょっとGithubの草(Public Contributionsのグラフ)を自前で取得できないか、と考えてもにょもにょして、ようやくできたのでメモしておきます。 「できないかな?」と思い付いた直後にググったところ、自分の GitHub の草状況に毎日向き合うライフハック – えいのうにっきの記事を拝見して「あ、できるのか」と思い。 上記サービスを利用しても良かったのですが、折角なので勉強がてら自分で作れないかとチャレンジしました。 結果としてできたのが以下になります。 草を取ってくるので草に関連する名前をリポジトリ名に、と思い鹿屋野比売神の別名「野椎神」からノヅチです。……ノヅチというとツチノコの別名を連想する方の方が多そうですが。 中身的にはクロスオリジン、CORSの関係でJavaScriptで直接Githubを参照するのは難しそうだったので、一旦間にPHPを挟むことにしました。 結果、以下のように無事取得できました。
Githubの草を取得してページに描画した様子
Githubの草を取得してページに描画した様子
仕組みとしては、
  1. JavaScript(axios)からはPHPのURLにユーザIDをパラメータとして投げる
  2. そのパラメータを使ってPHPはGithubのユーザトップページにアクセス
  3. PHPは戻ってきたテキストをそのままクライアントに投げ返す
  4. JavaScript(cherrio)は受け取った文字列からHTMLを解析、svgの部分のみを抽出してページを書き換え
という形です。

コード

まずはJavaScriptの方。
import axios from 'axios'
import htmlparser from 'htmlparser2'
import cheerio from 'cheerio'

const axiosApi = axios.create({
    xsrfHeaderName: 'X-CSRF-Token',
    withCredentials: true,
    timeout: 10000
}) //PHPに頼るので不要ですが一応ヘッダに付与
Promise.all([
    axiosApi.get('http://localhost/weeding.php?user=USERNAME'), //ユーザ名をGETパラメータで指定して同ドメインのPHPへアクセス
]).then(([result]) => {
    if(result.status >= 400) { //エラー
        resolve(new Error())
    }
    else { //正常
        const dom = htmlparser.parseDOM(result.data) //レスポンスをhtmlparser2でパース
        const $ = cheerio.load(dom)
        let grassfield = document.getElementById('grass') //HTMLにあるid="grass"を取得、結果をHTMLに書き換える準備
        grassfield.innerHTML = $('div.js-calendar-graph.graph-canvas').html() //'div.js-calendar-graph.graph-canvas'の子要素のHTMLを丸ごと書き換え
    }
})
次にPHP。
<?php
$url = 'https://github.com/' . htmlspecialchars($_GET['user'], ENT_QUOTES, 'UTF-8') . '/';
$data = file_get_contents($url);
header("Access-Control-Allow-Origin: *");
header("Content-Type: text/plain");
echo $data;
CORSのためにheader("Access-Control-Allow-Origin: *");を記述しています。 あと、ササッと作るためimportの絡みでバベるのは面倒だと思ったので、axiosやcherrioはgulp-parcelを使って1ファイルにまとめています。 ということで、できることが分かったので良かったです。

参考

JavaScriptでスクレイピング

Github Grassを取得するサービス

この記事を書いた人

アバター

アルム=バンド

フルスタックエンジニアっぽい何か。LAMPやNodeからWP、gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。