最近、GitHub API を使ってリポジトリ情報を取ることが多いのですが、REST API より GraphQL を使ったほうが必要な情報だけを一気に取れるということを耳にし、試してみることにしました。
Query を作成
GraphQL はクエリの書き方が特殊なので REST API を普段使う人にとっては最初とっつきにくい感じを受けます。最初に指定できるのは Query という分類をされているもので、GitHub API のドキュメントに一覧が載っています。
この中から欲しい情報を選ぶのが最初のステップです。ここでは user
にしてみましょう。上のリンクの一番下に user
の説明があります。変数として login
のみを指定できるようですね。これは String 型です。試しに私の情報を取ってみます。
{ user(login: "Hayashi-Yudai") }
指定できました。これだけでは実行しても指定した情報が足りずエラーが出てしまいますので情報を追加していきます。user
は User
型を返すと書いてある(user の横に青文字で User と書いてある)のでリンクをクリックして User 型がどのような情報をもっているのか見てみます。
commitComments
や followers
など色々あります。issues
というのがあるのでこれを取ってみましょう。引数として first
が取れるのでこれを10にして最初の10個を取ってみます。
{ user(login: "Hayashi-Yudai") { issues(first: 10) } }
issues
の中には edges
やnodes
などが入っています。こんな調子でどんどん深くまでたどっていくと、
{ user(login: "Hayashi-Yudai") { issues(first: 10) { nodes { body } } } }
というクエリを書くことができます。一番深いところにある body
は型が String なのでこれ以上深いところには何もありません。
Query を実行する
では最後に上で作成したクエリを Python で実行してみます。
import requests import os headers = {"Authorization": f"Bearer {os.environ.get('GITHUB_TOKEN')}"} def run(query): request = requests.post( 'https://api.github.com/graphql', json={'query': query}, headers=headers ) if request.status_code == 200: return request.json() else: raise Exception(f"Query failed to run by returning code of {request.status_code}. {query}") query = """ { user(login: "Hayashi-Yudai") { issues(first: 10) { nodes { body } } } } """ result = run(query)
GitHub Access Token は私の場合には環境変数に指定しているので os.environ.get
で取ってきてヘッダに入れています。result の中身を見てみると
{'data': { 'user': { 'issues': { 'nodes': [ {'body': 'When I run some codes, text garbling happened. I tried hello world program by\r\n\r\n* Python3\r\n* Java\r\n* C\r\n* C++ \r\n\r\nbut, only in C and C++, text garbling happened.'}, {'body': 'In HTML, the width of `th` component is assigned like "5%", but it does not reflected in the page.'}, {'body': 'add regularization and batch-normalization to transposed convolution layer'}, {'body': 'add the pooling layer'}, {'body': 'create UNet by components I prepared.'}, {'body': 'To training UNet model, I should change input images to one-hot representation'}, {'body': 'create training session'}, {'body': 'To evaluate the model, I should set metrics such that accuracy or loss'}, {'body': 'show training result as images'}, {'body': 'To split training and validation of the model, I should give the is_training parameter when running the session.'} ] } } }}
これを見てみると user -> issues -> nodes -> body という構造になっていてクエリで書いた構造と同じ構造でレスポンスが返ってきていることが分かります。