Qiita API を使って、特定の日の記事データを取得する方法

## はじめに
初学者です。最近WebAPIについて学ぼうとしていて、以下記事でまとめているように基本的な知識やTwitter APIを使ってみたりし始めました。
その延長として、QittaAPIも扱えるようにしたいと思い挑戦しましたが、初心者的なところでよく躓いていたので、トラブったところを残しておきます。誰かの助けになれば幸いです。
本当にQitta全てのユーザに感謝。

＜参考：WebAPIについてまとめた記事＞
- [Web APIについて](https://kissshot-skup.github.io/webpage/webapi/)
- [【情報処理】AWSでwebhookの受信＆メール通知を実装する（API Gateway＋Lambda）](https://kissshot-skup.github.io/webpage/webhook/)
- [Web APIでbotを作ろう！](https://kissshot-skup.github.io/webpage/webapi2/)


## QittaAPIの登録から記事取得をするまでの流れ
以下記事で紹介されている流れに従って作業を進めました。
[Qiita API を使って、記事データを取得する方法](https://qiita.com/wakudar/items/8c594c8cc7bda9b93b4e)

ただ、初学者ならではの躓いたポイントを一個ずつ以下にメモっていきます。

## 取得したアクセストークンの記入の仕方
上記参考記事では以下コードを記述とあります。
```
# ユーザ認証に必要なヘッダー
h = {'Authorization': 'Bearer 【取得したアクセストークン】'}
connect = http.client.HTTPSConnection("qiita.com")
url = "/api/v2/items?"
```
まず、“取得したアクセストークン”とあるけどBearerというところの後にベタ書きすればいいのか、不安になりました。【】は流石にいらないよなと思ったり。←そんなとこで躓くなよ！と怒られそうですが。。。

結論、QittaAPIのドキュメントのサンプル↓のようにベタ書きでOK。
[Qiita API v2の仕様](https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF)
```
Authorization: Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd
```
つまりサンプルのアクセストークンで書くとこんな感じ
```
h = {'Authorization': 'Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd'}
```

と、こんな具合に、ベテランからしたらそこ！？と言われそうなところで不安になっちゃんですよね。

で、その後に続くコードも実行してみて、サンプルコードを解読していったのですが、結構時間がかかりました。
ので、どこがどうなっているのか1個ずつ動くかどうか試していきたい気持ちがあってたどり着いたのは、以下の方法です。

## API Testerを使って認証が通る&スポット的にQittaAPIが使えるかまず試そう
API Testerはブラウザ経由でHTTP通信を試しに投げられるツールですが、以下を使っています。Googleの拡張機能でいけるので、簡単です。
[API Tester](https://chromewebstore.google.com/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=ja&pli=1)

さっそく取得したアクセストークンとサンプルのGETコマンドでまず使えるかを試して、一個ずつ不安を消していきましょう。
以下のような感じ。
![スクリーンショット 2023-11-11 004703.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2639414/bf978624-dfbf-747b-c074-58004af66f99.png)

赤字矢印の箇所にコマンドやアクセストークンを記載して、「Send」ボタンを押してみましょう。
サンプルのURIおいておきます
```
https://qiita.com/api/v2/items?query=created:>=2019-04-28 created:<=2019-04-28&per_page=100
```
成功すれば、青字矢印のRespons欄に200番のresとBODYに取得した内容が記載されます。

ここまでで、**私のアクセストークンはちゃんと利用できてて、ちゃんとコード書けば動く！**
という自信はつきました。


## 提供されたサンプルコードを動かしてみる
ある特定の日の記事を取得したくて、以下記事で紹介されているサンプルコードを借用させてもらおうと挑戦しました。
[Qiitaの記事情報をAPIで取得しCSVに書き出す](https://qiita.com/ararie/items/94902fc0e686e59cb8c5)

べた書きしてまずは動かしてみましょう。ここで、下手にいじると何がなんだかわからなくなります。私は日付をいじってみたりしてたので、動かなくてあくせくしていました。

そのままベタ書きでは動くと思います。VSCodeでPythonファイルを作り、コピペで実行して確認しました。
ただ、以下サンプルコードの日付を特定の日にしてみたり（他のサンプルコードの箇所も調整する必要あり）、他の日付にしたりしたら、うまく動かない沼にハマりました。
```
start = '2019-04-15'
end = '2019-06-30'
```

## pandasの使い方をちゃんと調べよう
問題は、pandasの使い方がわかっていなかった！！
以下コード部分のfreq='SM'は半月毎の日付を取得するので、特定の日付を取得する場合は'D'にする必要がありました。
多分色々間違っている&もっとキレイなコードで書けるのでしょうが、こんな感じに直し
```
# この期間に作成されたQiitaの記事情報を取得
start = '2019-04-28'
end = '2019-04-28'

# 日付をリスト化
date_list = [d.strftime('%Y-%m-%d') 
             for d in pd.date_range(start, end, freq='D')]
```

ある特定の日ということで、もはやlist型でなくてもよいかもですが、このまま元コードを最大限活用行きましょう。

## 特定の日の記事を取得してCSV出力する部分
サンプルコードに記載の半月毎に取得する仕組みを削って&修正して本体部分は以下にしました。
```
import http.client
import json
import pandas as pd
import math

h = {'Authorization': 'Bearer xxxxxxxx自分のアクセストークンxxxxxxxx'}
conn = http.client.HTTPSConnection("qiita.com")
url = "/api/v2/items?"

# この期間に作成されたQiitaの記事情報を取得
start = '2019-04-28'
end = '2019-04-28'

# 日付をリスト化
date_list = [d.strftime('%Y-%m-%d') 
             for d in pd.date_range(start, end, freq='D')]
print(date_list)

# カウント用変数
num = 0
p = 0

# start_listの配列の数だけ繰り返し処理　←今回は1日なのであまり意味ない
for i in date_list:
    num += 1
    # 日付のリストから検索の開始日と終了日を取り出す
    search_date =  date_list
    query = "&query=created:>=" + search_date[0] + "+created:<=" + search_date[0] + "&per_page=100"
     # 検索で指定した日に作成された記事数を取得
    conn.request("GET",  url + query, headers=h)
    res = conn.getresponse()
    res.read()
    print(res.status, res.reason)
    print(res.headers['Total-Count'])
    total_count = int(res.headers['Total-Count'])
    # 取得した記事数をもとにリクエスト回数を算出
    page_count = math.ceil(total_count / 100)
    print(search_date[0] + "のデータを取得します...")
    print("この日に作成されたデータを取得するのに必要なリクエスト回数は" + str(page_count) + "回です")
    #データを取得しCSVに書き出す
    for p in range(page_count):
        p += 1
        page = "page=" + str(p)
        conn.request("GET", url + page + query, headers=h)
        res = conn.getresponse()
        print(res.status, res.reason)
        data = res.read().decode("utf-8")
        df = pd.read_json(data)
        print(df)
        df.to_csv("qiita2.csv", encoding="utf-8", columns=[
            'likes_count', 
            'created_at',
            'title',
            'url'
            ], mode='a', header=False, index=False)
        print(str(p) + "/" + str(page_count) + "完了")

```
これでCSVに特定日の記事一覧が書き出されるのを確認しました。
まず動かすことにフォーカスしており、コードの綺麗さ追求や想定外のバグがあるかもしれませんので悪しからず。。

## CSV出力するとタイトルが文字化けしとるがな！な場合
CSV出力部分を以下に変えて、テキストでJsonを吐き出すようにしてみました。

```
        filename = "./page" + str(page_count) + "-" + str(p) + ".txt"
        df.to_csv(filename, encoding="utf-8", columns=[
            'likes_count', 
            'created_at',
            'title',
            'url'
            ], mode='a', header=False, index=False)

```
これで確認する限り、文字化けはしていません。CSVに吐き出すとき特有の問題だとわかりました。
ググったり、ChatGPTさんに聞いたところ、文字コード変換が問題とのこと、以下に直せばOK。

```
        # df.to_csv("qiita2.csv", encoding="utf-8", columns=[
        # ↑は文字化けするので、↓に変更
        df.to_csv("qiita2.csv", encoding="utf_8_sig", columns=[
```
[参考にしたサイト](https://www.yoshiislandblog.net/2022/02/05/pandas_csv_excel/)

で、直らないって人は、qitta2.csvを一回消してから実行してみてください。
前のファイルを上書きできていないだけと思います。

## クエリをいじったりして、他の情報もとりたい
以下サイトを参考にしてGETコマンドを色々変えてみて試すのはありと思います。
[Qiita の記事一覧 API でも検索クエリに絞り込みオプションが使える](https://qiita.com/yonex/items/d3ade7c1ae9897536b28)


## 最後に
もっと他にも引っかかったところがあった気がしますが、また追記して補足していこうと思います。
これを皮切りにBotとの連携も考えて行きます。