YouTube Data API v3で２万件のコメントを取得する際の覚書

## はじめに

YouTube Data API v3を利用して、YouTube動画からコメントを取得する際の覚書です。

## YouTube Data API v3の制限
Google Colabを使い、

以下の記事を参考にして、
https://qiita.com/yaju/items/3bec88dbd544502e1343

こちらの動画のコメントを全部取得しようと思ったのですが、
https://www.youtube.com/watch?v=mLW35YMzELE

やってみたら、20000件以上のコメントがついているのに、1233件しか取得できませんでした。(2024年5月26日現在)

```python
import requests
import json
import pandas as pd

URL = 'https://www.googleapis.com/youtube/v3/'
# ここにAPI KEYを入力
API_KEY = 'APIキー'
# ここにVideo IDを入力
VIDEO_ID = 'mLW35YMzELE'

# 空のDataFrameを作成
df = pd.DataFrame()

def get_video_comment(video_id, next_page_token):
  params = {
    'key': API_KEY,
    'part': 'snippet',
    'videoId': video_id,
    'order': 'relevance',
    'textFormat': 'plaintext',
    'maxResults': 100,
  }
  if next_page_token is not None:
    params['pageToken'] = next_page_token
  response = requests.get(URL + 'commentThreads', params=params)
  resource = response.json()

  for comment_info in resource['items']:
    # コメント
    text = comment_info['snippet']['topLevelComment']['snippet']['textDisplay']
    new_row = pd.DataFrame({'テキスト': [text]})
    global df  # グローバル変数として df を参照
    df = pd.concat([df, new_row], ignore_index=True)

  if 'nextPageToken' in resource:
    get_video_comment(video_id, resource["nextPageToken"])

# コメントを全取得する
video_id = VIDEO_ID
get_video_comment(video_id, None)

print(df)
```
　Comments
0     A Guide To Creepy Nuts\nhttps://www.youtube.co...
1                         運動会の旗のダンスに使わせてもらいました。盛り上がってます
2     1期放送当時は作画も良くて話も面白かったけどほぼ話題にならなかったのにこの歌を機にマッシュル...
3     この曲の中毒性は、赤ちゃんをも笑顔にするというデータが出ておる…曲を聴いた全てものが楽しく、...
4                            2ヶ月経っても人気一位のミュージックビデオなのえぐい
...                                                 ...
1229                                               え、ひど
1230                                            这首歌很难听！
1231                     This is the dumbest song evevr
1232                                 あんま好きじゃないです。ごめんなさい
1233                                   I hate this song

[1234 rows x 1 columns]

返信コメントは省いているのですが、それでも少なすぎます。

よく読むと、先ほどの記事にこのような記載がありました。

>並び順を評価順(relevance)にした場合、YouTube Data API v3の制約上2000件を超える親コメントが取得できません。
並び順を新しい順(time)にした場合、上限が不明ですが2000件を超える親コメントが取得できます。

どうやらYouTubeのData APIに制限があるみたいですね。

## 並び順をtimeに変えてみる

　Comments
0      A Guide To Creepy Nuts\nhttps://www.youtube.co...
1                                           2038年に見てる人ー!
2                               プリンプリンプリンバンバンボーンと歌詞最高です。
3                                         2024年も聴いてる人いる？
4                                  2ヶ月まえか…さすがに誰も聴いてないはず❤
...                                                  ...
20582                                               きたか…
20583                                          カッコイイなマジで
20584                                            待ってた！！！
20585                                                  お
20586                                                最高！

[20587 rows x 1 columns]

できました！
……と思っていたのですが、何度も試してみると、何故か取得数が不安定になりました。
時々100件しかコメントを取得できない時があります。

## 上手くいった方法

以下のブログに書いてあった方法で上手くいきました。
https://nariyoo.com/python-collecting-youtube-comments-by-using-youtube-data-api/

```python
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import pandas as pd

DEVELOPER_KEY = 'APIキー'
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'

def get_video_comments(service, **kwargs):
    comments = []
    results = service.commentThreads().list(**kwargs).execute()

    while results:
        for item in results['items']:
            comment = item['snippet']['topLevelComment']['snippet']['textDisplay']
            comments.append(comment)

        # check if there are more comments
        if 'nextPageToken' in results:
            kwargs['pageToken'] = results['nextPageToken']
            results = service.commentThreads().list(**kwargs).execute()
        else:
            break

    return pd.DataFrame({'Comments': comments})

    comments_df = None

def main():
    global comments_df

    # Build the service
    youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)

    # Get the comments
    video_id = 'mLW35YMzELE'
    comments_df = get_video_comments(youtube, part='snippet', videoId=video_id, textFormat='plainText')

if __name__ == '__main__':
    main()

print(comments_df)
```

　Comments
0      A Guide To Creepy Nuts\nhttps://www.youtube.co...
1                               プリンプリンプリンバンバンボーンと歌詞最高です。
2                                         2024年も聴いてる人いる？
3                                  2ヶ月まえか…さすがに誰も聴いてないはず❤
4                        ay my rivals are all telling me
...                                                  ...
20581                                               きたか…
20582                                          カッコイイなマジで
20583                                            待ってた！！！
20584                                                  お
20585                                                最高！

[20586 rows x 1 columns]

さっきと1個差がありますが、YouTubeコメントの数は変化するので、これで大丈夫なはずです。

## おわりに
なぜ上手くいくのかは……よくわからないのですが、
Google API Python クライアント ライブラリを使うといいのかもしれません。

初心者ですみません、わかる人いたら教えてくれると嬉しいです。
ひとまず覚書として残しておきます。