Qiita APIとPythonを用いてQiitaのデータを取得してみる

Qiita APIPythonを用いてQiitaのデータを取得してみる

Qiita APIを使用すると、Qiitaサイトにあるデータを取得できます。PythonでQiita APIをたたき、データを取得してみます。


APIを調べる

Qiita API v2公式サイト

Qiita APIの詳細はすべてこちらに書かれています。

https://qiita.com/api/v2/docs


使えそうなAPIを探す

今回は、記事についているタグをキーに記事一覧を取得してみます。

「タグ」や「投稿」あたりを見てみて、タグをキーに記事を取得できそうなAPIを探します。


以下のAPIが使えそうでした。

GET /api/v2/tags/:tag_id/items

指定されたタグが付けられた記事一覧を、タグを付けた日時の降順で返します。


お試しでAPIを呼んでみる

APIの呼び出し(パラメータなし)

まずは、Pythonで上記のAPIをパラメータなしでたたき、データを取得してみます。


requestsモジュールのインストール

pip install requests

APIをたたいてみます。

import requests
res = requests.get('https://qiita.com/api/v2/tags/python/items')
print(res.text)
[{"rendered_body":"\u003cp\u003ePythonでOAuth認証を突破して、アクセストークンを取得するスクリプトを書きました。 \u003cbr\u003e\n解説などはあとで書き加えたいと思います。\u003c/p\u003e\n\n\u003cp\u003e\u003ca href=\"https://qiita.com/kai_kou/items/d03abd6012f32071c1aa\" class=\"autolink\" id=\"reference-
...

JSONが返ってきており、中身に記事の中身らしきものが含まれているのが見えます。JSONのフォーマットもAPIリファレンスに書かれたフォーマットになっています。

APIの呼び出し自体はうまくいってそうですね。


APIの呼び出し(URLクエリ)

もう少し条件を付けてみます。APIリファレンスのサンプルに書かれている、pageとper_pageのオプションをURLのクエリにつけて呼び出してみます。

import requests
res = requests.get('https://qiita.com/api/v2/tags/python/items?page=1&per_page=10')
print(res.text)

これも問題なく取得できました。


APIの呼び出し(JSONクエリ)

パラメータが多いとパラメータを変えながら渡すのが大変なため、あらかじめクエリをJSONで作り、それを渡します。

import requests
import json

p = {
    "page": "1",
    "per_page": "5",
}
res = requests.get('https://qiita.com/api/v2/tags/python/items', params=p)
print(res.text)

同じデータが返ってきたのが確認できました。

なお、この書き方であればエンコードなども自動でやってくれるそうです。


JSONモジュールで読み込む

上記のデータを、JSONを処理するモジュールに読み込ませてみます。

import requests
import json

res = requests.get('https://qiita.com/api/v2/tags/python/items?page=1&per_page=5')
jsondata = json.loads(res.text)
print(len(jsondata))
5

JSONモジュールで読みこめて、lenで5個あることが確認できました。


APIドキュメントを見ると、JSONに"id"および"title"という項目があるのが分かるので、その部分を取り出してみます。

for item in json:
    print(item['id'])
    print(item['title'])
16e88f7a85f82d7afac8
OAuth認証してアクセストークンを取得する
715aba6db368f53b3a2e
VBAユーザがPython・Rを使ってみた:行列
2b5523eede2e0c088f92
[Blender] Modeling tips まとめ Mesh Modeling編
55daf41e925a969aa5b5
Docker-compose + Django + MySQL + Nginx + uwsgi を使った環境の初期設定
c350f64b7abb396973ed
【pytorch-lightning入門】torchvision.transformsの使い方と自前datasetの自由な作り方?

idとtitleが取り出せました。JSONの中身も問題ないようです。


認証

API呼び出しの制限

API呼び出しは、未認証ユーザであれば1時間に60回までリクエストの制限があります。認証することで、1時間に1000回まで呼び出せるようになるため、認証をしておきます。


アクセストークンの発行

APIドキュメントの「認証許可」の項目を見ると、ユーザ管理画面からアクセストークンを発行できるようなので、ユーザ管理画面に行きます。

https://qiita.com/settings/applications


Qiitaにログイン後、「個人用アクセストークン」のところに「新しくトークンを発行する」のリンクから発行できます。

説明は分かりやすいように文章を記載、スコープはひとまず「read_qiita」だけでよいです。

発行ボタンでトークンが発行されます。なくさないようにメモっておきましょう。


認証してみる

APIドキュメントの「認証認可」内、「アクセストークン」の部分に、トークンをヘッダに含めればいいと記載あり。コードに追加してみます。

import requests
import json

token = "=====paste=your=token=here====="
headers = {
    "Authorization": "Bearer " + token
}
params = {
    "page": "1",
    "per_page": "5",
}
res = requests.get('https://qiita.com/api/v2/tags/python/items', params=params, headers=headers)
print(res.text)

先ほどのコードと同じ結果が返ってきました。問題なく認証されて呼び出せました。


記事を取得する

先ほどの処理で記事一覧が取得できたので、そのidを使って記事本文を取得してみます。


使用するAPI

APIリファレンスの「投稿」あたりを見てみると、以下が使えそうでした。

GET /api/v2/items/:item_id

記事を取得します。


呼び出し

先ほどの認証処理のあとに、記事取得APIを記事数回呼び出し、各記事の情報を取得します。

APIリファレンスによると、戻りJSON内に"tags"の項目があり、その中にタグがリストで返ってくるようなので、それをjsonモジュールで解析して画面に出してみます。

import requests
import json

token = "=====paste=your=token=here====="
headers = {
    "Authorization": "Bearer " + token
}
params = {
    "page": "1",
    "per_page": "5",
}
res = requests.get('https://qiita.com/api/v2/tags/python/items', params=params, headers=headers)
jsondata = json.loads(res.text)
for item in jsondata:
    print(item['id']) # 記事IDを出力
    res = requests.get('https://qiita.com/api/v2/items/' + item['id'], headers=headers)
    json_content = json.loads(res.text)
    for tag in json_content['tags']:
        print(tag['name']) #記事のタグを出力
a3b1dfbc580608dd4e10
Python
再帰関数
580d000d1eda58bfa8b4
Python
gspread
slackbot
16e88f7a85f82d7afac8
Python
OAuth
HTTPS
715aba6db368f53b3a2e
Python
R
VBA
配列
行列
2b5523eede2e0c088f92
Python
Blender

記事ごとのタグ一覧がすべて出力されました。


タグの数を数えてみる

データは取得できたので、あとは好きに加工すればよいです。

今回は、タグの数を数えてみます。tag_cnt変数でタグをカウントしていきます。

import requests
import json

token = "=====paste=your=token=here====="
headers = {
    "Authorization": "Bearer " + token
}
params = {
    "page": "1",
    "per_page": "5",
}

# 「python」タグがついた記事一覧を取得
res = requests.get('https://qiita.com/api/v2/tags/python/items', params=params, headers=headers)
jsondata = json.loads(res.text)

tag_cnt = {}
for item in jsondata:
    # 各記事を取得
    res = requests.get('https://qiita.com/api/v2/items/' + item['id'], headers=headers)
    json_content = json.loads(res.text)
    # 記事の各タグについて
    for tag in json_content['tags']:
        # カウント処理
        if tag['name'] in tag_cnt:
            tag_cnt[tag['name']] += 1
        else:
            tag_cnt[tag['name']] = 1

# カウントした値を出力
for key, value in tag_cnt.items():
    print(key, value)
Python 5
再帰関数 1
gspread 1
slackbot 1
OAuth 1
HTTPS 1
R 1
VBA 1
配列 1
行列 1
Blender 1

Pythonで検索しているのでPythonが一番多く5個、Pythonタグとともについているタグがどういったものかが分かりました。


900記事を取得する

上記では、ページ当たりの記事数を5個とし、その1ページ目だけを取得しました。このカウントを増やし、900記事分を取得してみます。

最初のAPI(GET /api/v2/tags/:tag_id/items)の説明によると、同時に取得できる記事一覧の数は100個までなので、100個の記事を9回取得します。

1回の処理でAPI呼び出しが101回行われるため、9回繰り返すと合計909回のAPI呼び出しとなり、API呼び出し制限1000回を下回ります。

import requests
import json

token = "=====paste=your=token=here====="
headers = {
    "Authorization": "Bearer " + token
}

tag_cnt = {}
for i in range(9):
    params = {
        "page": str(i + 1),
        "per_page": "100",
    }
    # 「python」タグがついた記事一覧を取得
    res = requests.get('https://qiita.com/api/v2/tags/python/items', params=params, headers=headers)
    jsondata = json.loads(res.text)

    for item in jsondata:
        # 各記事を取得
        res = requests.get('https://qiita.com/api/v2/items/' + item['id'], headers=headers)
        json_content = json.loads(res.text)
        # 記事の各タグについて
        for tag in json_content['tags']:
            # カウント処理
            if tag['name'] in tag_cnt:
                tag_cnt[tag['name']] += 1
            else:
                tag_cnt[tag['name']] = 1

# カウントした値を出力
for key, value in tag_cnt.items():
    print(key, value)
Python 900
AWS 23
lambda 25
Slack 7
ServerlessFramework 4
Python3 110
gspread 3
slackbot 3
Twitter 7
tweepy 3
自然言語処理 13
NLP 2
WordNet 1
環境構築 11
Anaconda 14
・・・

取得に数分かかりましたが、無事取得できました。


CSV出力する

取得して集計したデータをCSVに出力してみます。

with open("output.csv", "w", encoding='utf-8') as f:
    for key, value in tag_cnt.items():
        f.write('"' + key + '", ' + str(value) + "\n")

output.csvが作成され、画面に出ていた出力結果がcsvに書き出されました。