Qiita API v2 で記事取得する (Ruby)

[@koshi_life](https://twitter.com/koshi_life) です。

DB検証用にある程度まとまったデータが欲しかったので、
[Qiita API v2](https://qiita.com/api/v2/docs)で過去記事を取得するコードをRubyで書いてみました。

### 前提

- ruby v2.6

## 書いたコード

```qiita_api_manager.rb
# coding: utf-8
require 'net/http'
require 'json'

class QiitaApiManager
  PER_PAGE = 100
  ACCESS_TOKEN = '<YOUR ACCESS TOKEN>'
  GET_ITEMS_URI = 'https://qiita.com/api/v2/items'

  def self.search(query, page: 1)
    puts "API Search Condition: query:'#{query}', page:#{page}"

    # リクエスト情報を作成
    uri = URI.parse (GET_ITEMS_URI)
    uri.query = URI.encode_www_form({ query: query, per_page: PER_PAGE, page: page })
    req = Net::HTTP::Get.new(uri.request_uri)
    req['Authorization'] = "Bearer #{ACCESS_TOKEN}"

    # リクエスト送信
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    res = http.request(req)

    # 次ページを計算 (API仕様 上限は100ページ)
    total_page = ((res['total-count'].to_i - 1) / PER_PAGE) + 1
    total_page = (total_page > 100) ? 100 : total_page
    next_page = (page < total_page) ? page + 1 : nil

    # API 残り使用回数、リセットされる時刻を表示
    puts "API Limit:#{res['rate-remaining']}/#{res['rate-limit']}, reset:#{Time.at(res['rate-reset'].to_i)}"

    # 返却 [HTTPステータスコード, 次ページ, 記事情報の配列]
    return res.code.to_i, next_page, JSON.parse(res.body)
  end
end
```

## 利用例

```.rb
query = 'created:>=2019-04-01 created:<=2019-04-01' # 参考 検索時に利用できるオプション
status, next_page, items = QiitaApiManager.search(query)
items.each {|item| puts "[#{item['created_at']}] #{item['user']['id']} wrote '#{item['title']}'"}
```

出力結果

```.txt
API Search Condition: query:'created:>=2019-04-01 created:<=2019-04-01', page:1
API Limit:644/1000, reset:2019-04-21 21:32:55 +0900
[2019-04-02T08:53:37+09:00] tech_kitara wrote 'ポート管理表+パラメータ表+Jinja2テンプレートから、L2SWのConfigを自動生成してみた'
[2019-04-02T08:51:20+09:00] takeshikondo wrote 'Django + GCP (GAE, Vision API, Translate API, Cloud Storage, Cloud Firestore) で画像アプリをデプロイする。 '
[2019-04-02T08:17:05+09:00] V_PG_N wrote '初めてのオリジナルWebサービス'
[2019-04-02T08:00:14+09:00] kai_kou wrote 'macOS Mojave 10.14.4のSafariがカスタムカラー設定に対応しているWebサイトでダークモードに対応したらしいので試してみた'
[2019-04-02T07:44:18+09:00] Mizu_e wrote 'Sass(Scss)  学習記録'
...
```

>https://qiita.com/api/v2/docs#get-apiv2items
>記事の一覧を作成日時の降順で返します。

4/1の作成日時を対象とした条件で記事検索をしてみましたが、
4/2 8時台(日本時刻)が入っているということは、日時検索条件はUTC時刻を元に行われるっぽいですね。推測です。(API仕様には記載なし)

## 参考

- [Qiita 検索時に利用できるオプション](https://help.qiita.com/ja/articles/qiita-search-options)
- レスポンスヘッダ例 (適度にマスクしてます)

```
HEADER: date Sat, 21 Apr 2019 21:00:00 GMT
HEADER: content-type application/json; charset=utf-8
HEADER: transfer-encoding chunked
HEADER: connection close
HEADER: server nginx
HEADER: x-frame-options SAMEORIGIN
HEADER: x-xss-protection 1; mode=block
HEADER: x-content-type-options nosniff
HEADER: x-download-options noopen
HEADER: x-permitted-cross-domain-policies none
HEADER: referrer-policy strict-origin-when-cross-origin
HEADER: link <https://qiita.com/api/v2/items?page=1&query=created%3A%3E%3D2019-04-01+created%3A%3C%3D2019-04-01>; rel="first", <https://qiita.com/api/v2/items?page=2&query=created%3A%3E%3D2019-04-01+created%3A%3C%3D2019-04-01>; rel="next", <https://qiita.com/api/v2/items?page=3&query=created%3A%3E%3D2019-04-01+created%3A%3C%3D2019-04-01>; rel="last"
HEADER: total-count 314
HEADER: etag W/"xxxxxxxxxxxxx"
HEADER: cache-control max-age=0, private, must-revalidate
HEADER: rate-limit 1000
HEADER: rate-remaining 644
HEADER: rate-reset 1555849975
HEADER: vary Origin
HEADER: x-runtime 0.379955
HEADER: strict-transport-security max-age=2592000
HEADER: x-request-id xxxx-xxx-xxx-xxx-xxx
```