YouTubeデータ、試してみませんか？

# はじめに
　こんにちは、@kanure24です。
本記事は、 *Advent Calendar 2023 - 身の回りの困りごとを楽しく解決！ by Works Human Intelligence* の22日目として投稿させて頂いております！

今年の僕の困りごとは、何かと話題になったX (旧Twitter)のAPI仕様変更により、研究の方針を変えざるを得ないことでした。そこで、新たなデータ源として、YouTubeのテキストデータを簡単かつ実用的に収集できるなライブラリを作成しました。
本記事では「習うより慣れろ」ということで、10分で実際に手元でYouTubeデータを収集できるような構成としているので、ぜひご覧ください！

https://github.com/momijiro/youtube_data_collector

コードや記事に対し、間違っている点や疑問点・不明点等ありましたらご連絡いただけると幸いです。

### 目次

[1. 爆速トライ](#1-爆速トライ) (10分)
[2. まとめ](#2-まとめ) (1分)
[3. 詳しい使い方](#3-詳しい使い方) (気になる方向け)


## 1. 爆速トライ
とにかく使ってみていただきたいので、
(1) ライブラリをインストール 
(2) APIキーを取得 
(3) コード実行
と最短でYouTubeデータを収集する方法を説明します。

#### (1) ライブラリをインストール (1分-)
　まず下記のコードを実行します。環境によっては別のライブラリのインストールに時間がかかる場合があるので、先にやってしまいましょう。
   ```python
   # 本ライブラリをインポート
   !git clone https://github.com/momijiro/youtube_data_collector
   # ディレクトリを変更 (notebookでの実行を想定)
   %cd youtube_data_collector
   # 関係するライブラリをインストール
   !pip install -r requirements.txt
   ```
#### (2) YouTube APIキーを取得 (3-5分程度)
　待っている間に、APIを実行するためのキーを発行します。ちなみにAPIの使用にお金はかかりませんが、1日の制限はあります(後述)。

##### 手順 (Googleアカウントは持っている前提としています)
1. [Google Cloud Plattform](https://console.cloud.google.com/)にアクセス
2. プロジェクトの新規作成 -> 選択
2. 「APIとサービス」の「ライブラリ」に移動
2. 「YouTube Data API v3」を検索し、有効にする
2. 「認証情報」の「認証情報を作成」でAPIキーを作成
2. (必要なら) キー制限をかける

##### 参考サイト (どちらの記事も分かりやすいのでお好みで)
- [@shinkai_さんのQiita記事](https://qiita.com/shinkai_/items/10a400c25de270cb02e4)
- [けーさんのブログ記事](https://ksanhonsan.com/youtube-apikey/)

#### (3) コード実行 (1分-)
　`YOUTUBE_API_KEY`を自分の取得したAPIキーに修正して実行することで、簡単にデータが収集できます。
```
# ライブラリをインポート
from ytdc import YouTubeDataCollector, pickup_video_id, update_list

# 実行
YOUTUBE_API_KEY = 'YOUR_API_KEY'  # 自分の API キーに置き換えてください
collector = YouTubeDataCollector(
        api_key=YOUTUBE_API_KEY,
        mode='movie',
        save=False,
        args = {
            'start': '2008-01',
            'end': '2008-01',
            'query': 'あけましておめでとう',
        }
)
collector.run()
df_movie = collector.df
df_movie
```
本コードでは、「あけましておめでとう」を含む2008年1月の動画データが収集できます。　ちなみに、quota (後述)を消費しすぎないように2008年としています。

#### 結果のイメージ (※実データではありません)
| video_id   | title   | description   | publish_time   | channel_title   |
|------------|---------|-------------|------------|----------------|
|ab12cd|あけましておめでとう動画|日の出の動画です|2008-01-01T01:23:45Z|Helloworld|
|zy34xw|新年あけましておめでとう|ハッピーニューイヤー！|2008-01-01T23:45:00Z|Dummies|

このように、動画のタイトル、概要、公開日時、チャンネル名を取得できます。その他、コメント、視聴回数、高評価数等も取得できます (後述)。

# 2. まとめ
　早いですが、ここで一旦まとめです。実際に手を動かしてくださった方は、ここまでで意外と簡単にYouTubeデータを収集できることを知っていただけたのではないでしょうか?
 
本記事で一番伝えたいことは以上ですが、より詳しく使ってみたい方は引き続きご覧ください！

# 3. 詳しい使い方
　続いて本章では実用面として、機能性・汎用性・実践面の３つに分けて紹介したいと思います！ ※ 本ライブラリの詳しい仕様は [Githubのdocs](https://github.com/momijiro/youtube_data_collector/tree/main/docs_ja)をご覧ください。

- 機能性：どんな機能があるの？
    - キーワードで動画を集めたい (説明済み)
    - [チャンネルを指定したい](#チャンネルを指定したい)
    - [コメントを集めたい](#コメントを集めたい)
    - [高評価数や視聴数を集めたい](#高評価数や視聴数を集めたい)
    - [データを保存したい](#データを保存したい)
- 汎用性：自分に合わせた設定にするには？
    - [クエリを詳しく指定したい](#クエリを詳しく指定したい)
    - [日付を指定したい](#日付を指定したい)
    - [ヒット数が多いデータを収集したい](#ヒット数が多いデータを収集したい)
- 実践面：実際に使うには?APIについてもっと知りたい！
    - [quotaとは](#quotaとは)
    - [再リクエストとは](#再リクエストとは)
    - [quotaは増やせないか](#quotaは増やせないか)
    - [全体像のまとめ](#全体像のまとめ)
- [最後に](#最後に)

### チャンネルを指定したい
　`mode='movie'`で、`args`で`'query'`の代わりに`'channel_id'`を用います。
```
collector = YouTubeDataCollector(
        api_key=YOUTUBE_API_KEY,
        mode='movie',
        save=True,
        args = {
            'start': '2008-01',
            'end': '2008-01',
            'channel_id': 'specify_channel_id',
        }
)
collector.run()
df_movie = collector.df
df_movie
```
ただし、`'channel_id'`は、`'ChannelTitle'`や「@」で始まるものではなく、そのチャンネルに固有のランダムな英数字です。 [こちらの方の記事](https://ilr.jp/tech/485/)を使わせていただくと、チャンネルURLを入力することで取得できます。

### コメントを集めたい
　コメントを集める場合は、先に`mode='movie'`で実行し、そのデータから`video_id_list`を作成する必要があります。
```
df_movie = collector.df   # mode='movie'での実行結果
video_id_list = pickup_video_id(df_movie)
```
この`video_id_list`を用いて、`mode='comment'`としてコメントを収集します。
```
collector = YouTubeDataCollector(
        api_key=YOUTUBE_API_KEY,
        mode='comment',
        save=True,
        args={'video_id_list': video_id_list}
)
collector.run()
df_comment = collector.df
df_comment

```
このようなコメントデータを取得できます。(イメージ)
現状の仕様では、低評価数は全て0となるので取得していません。

| video_id | comment  |like_count | publish_time  |author_id|
|---|---|---|---|---|
|ab12cd|めでたいなぁ  |5 | 2008-01-02T10:20:30Z |AAAAAAAAAabbbbbbbCC||
|ab12cd|今年もよろしく|2| 2013-01-23T12:34:56Z |DDDDDDDeeeeeeeeffffGG||

### 高評価数や視聴数を集めたい
　高評価数、視聴数等は`comment`モードと同様に`video_id_list`を指定し、`mode='stats'`とすることで実行できます。
```
collector = YouTubeDataCollector(
        api_key=YOUTUBE_API_KEY,
        mode='stats',
        save=True,
        args={'video_id_list': video_id_list}
)
collector.run()
df_stats = collector.df
df_stats
```
データとしてもこんな感じです。
|video_id  |View_count  |like_count  | comment_count|
|---|---|---|---|
|ab12cd|33333 |3|1|
|zy34xw|4321 |1|0|

### データを保存したい
　`save=True`とすると、以下のようにデータを保存することができます。(デフォルトでは`output`フォルダを作成)
- `movie` -> `output/movie/あけましておめでとう_2008-01_2008-01.csv`
- `comment` -> `output/comment/comment_lastvideoid.csv`
- `stats` -> `output/stats/stats_lastvideoid.csv`

`save_path`により保存先フォルダ、`file_name`によりファイル名を指定することができます。 (厳密には、ファイル名の後半部分は変更できないようにしてあります。詳しくはdocsやコードをご覧ください。)


### クエリを詳しく指定したい
　キーワード(`query`)は自由に設定可能で、複数羅列する場合は半角スペースで区切ります。Twitter API等と同様に、以下のように`AND`や`OR`を用いて検索することもできます。
```
'query': '(今日 OR 明日) AND (晴れ OR 雨)'
```
この例では、「今日・晴れ」を含む動画、「今日・雨」を含む動画、「明日・晴れ」を含む動画、「明日・雨」を含む動画が収集されます。

### 日付を指定したい
　動画の収集期間は、`start`と`end`で単位が同じなら、年・月・日のどれでも取得可能です。

(例) 2010年から2012年のデータを収集したい場合
|`start` |`end`|保存名の例|
|---|---|---|
|`'2010'`|`'2010'`|`キーワード_2010_2012.csv`|
|`'2010-01'`  |`'2010-12'`|`キーワード_2010-01_2012-12.csv`|
|`'2010-01-01'`  |`'2010-12-31'`|`キーワード_2010-01-01_2012-12-31.csv`|

上記の3パターンはどれも結果としては(原理上)同じになります。なので、長期間のデータを収集する場合は、API効率の観点からなるべく大きい単位 (年・月) を使用してください。 (詳しくは：[quotaとは](#quotaとは))


### ヒット数が多いデータを収集したい
　ある程度ヒット数が大きいデータを取得しようとすると、quotaが1日の上限を超え、複数回(日)に渡って収集しなければいけないことがあります。本ライブラリでは、ファイルの保存名の語尾 (`.csv`の前) により「どこまで収集したか」を表しているので、その次から収集することで無駄なく実行することができます。

|`mode` |ファイル名の語尾 (例)|語尾の意味|次回実行時|
|---|---|---|---|
|`'movie'`|`~_2012.csv`|何年 (何月・何日)まで収集したか|`start`を変更して実行|
|`'comment'`  |`~_lastvideoid.csv`|どの`video_id`まで収集したか|`video_id_list`を更新して実行(※)|
|`'stats'`  |`~_lastvideoid.csv`|どの`video_id`まで収集したか|`video_id_list`を更新して実行(※)|

※ ちなみに、以下の関数により`video_id_list`を更新する事ができます。
```
last_id = 'LastSavedVideoId'
video_id_list = update_list(video_id_list, last_id)
```

### quotaとは
　YouTube APIには「quota」というチャージの概念があり、1日あたり10,000 quota与えられています ([公式: API概要](https://developers.google.com/youtube/v3/getting-started?hl=ja))。 ただし、`mode`ごとに消費量が異なります。
|`mode` |1リクエストあたり消費量 |[公式サイト](https://developers.google.com/youtube/v3/determine_quota_cost?hl=ja)での記載方法|1日あたりの最大取得数(※)
|---|---|---|---|
|`'movie'`  |100 quota  |`検索-list`|100年(月・日)分の動画|
|`'comment'`|1 quota  |`コメントスレッド-list`|10,000動画のコメント|
|`'stats'`|1 quota  |`動画-list`|10,000動画の統計量|

#### この仕組みにより、注意すべき点は2つあります。

1. <u>**`movie`モードでは、同じ期間でも指定の仕方によって消費量が変わる**</u>
    
    　本ライブラリで年・月・日を指定できる仕様にしているのは、なるべく大きい単位で実行し、quota効率を上げるためです。例えば、2020年から2022年の3年分の動画データを取得する際の消費quotaは以下のようになり、同じ期間でも大きく変わることが分かります。
    |`start`|`end`|リクエスト数|最低quota消費量 (※)|取得にかかる最短日数|
    |---|---|---|---|---|
    |`2020`  |`2022`|`1*3=3`回|`100*3=300` quota|1日|
    |`2020-01`|`2022-12` |`12*3=36`回|`100*36=3,600` quota|1日|
    |`2020-01-01`|`2022-12-31` |`365*3=1095`回|`100*1095=11万` quota|11日|
    

2. <u>**検索でヒットするデータ数は、検索条件によって大きく異なる**</u>

    　例えば、レシピ動画を探そうとしたとき、条件を絞り込んだほうがヒット数は少なくなることは容易に想像できると思います。以下の`レシピ`のようにヒット数が1,000件もあると、1回のリクエストで全てのデータを収集できず、同じ条件で何度もリクエストする必要があります。
    |`query`|ヒット数（イメージ）|再リクエスト|
    |---|---|---|
    |`レシピ`  |1,000|あり|
    |`レシピ AND キャベツ AND 豚肉 AND 時短 `|30|なし|

このように、大量のデータを収集するためにはquota効率が重要になります。続いて「どれくらいで再リクエストするのか？」を説明します。

※ 1日あたりの「最大取得数」、1リクエストあたりの「最低quota消費量」は、再リクエストがない場合の取得数・消費quotaであることを意味しています。

### 再リクエストとは
　前章でも述べましたが、ヒット数が多い場合、1回のリクエストで全てを取得することはできません。1回のリクエストで取得できるデータ数( `maxResults` )は50ですが、50件を超える結果はざらにあります([公式: Search関数](https://developers.google.com/youtube/v3/docs/search/list?hl=ja))。
そこで、50件を超える時には「`PageToken`」というもので「まだ続くよ」とAPIが教えてくれます( Twitter API等でも同様の仕組みがあると思います)。

　本ライブラリではその仕組みを用いて、`PageToken`がある限り再リクエストする仕様としています。 例えば、先程の「レシピ」の例では、ヒットする動画数が1,000件なので、合計1000/50=20より20回リクエストを行います。本ライブラリでは、リクエスト回数(`request_count`)を表示するようにしているので、参考にしてみてください。

### quotaは増やせないか?
　quotaの一日の上限は `10,000quota` (動画取得リクエスト100回分、コメント10,000回分)です。この制限内でなるべく多くのデータを収集するため、本ライブラリではquota効率を重視し作成しています。
一方で、quotaを増やせないの？と思う方はいらっしゃると思います。答えはYesで、YouTubeに申請フォームを出し承認されれば増やせるようなので、詳しくは公式やその他の方の記事をご参照ください。しかし僕の場合は以下の3点から結局上限解除はしていません。
- 意外とステップが面倒くさい
- 上限解除に関する情報量があまり多くない
- 使用するquota数を申請するために本ライブラリを実装したら、自身の研究ではデータ数的に不要と気づいた

研究・サービス内容によっては上限解除申請をしたほうが良い場合も多々あると思いますので、本記事がその判断の一助となれば幸いです。


### 全体像のまとめ
　最後に、全体のまとめとしてコードの構造やモード間の違いについてここでまとめておきます。

#### [YouTubeDataCollector](https://github.com/momijiro/youtube_data_collector) のディレクトリ構成

```
youtube_data_collector
├── docs                # ライブラリの実行に関係する文書まとめ (英語)
│   ├── note.md         # 実行に関わる補足・注意点等
│   └── usage.md        # 詳しい使用方法
├── docs_ja             # ライブラリの実行に関係する文書まとめ (日本語)
│   ├── note_ja.md
│   └── usage_ja.md
├── LICENSE             # ライセンス
├── README.md           # 概要
├── requirements.txt    # 依存関係
├── setup.py            # セットアップ
└── ytdc
    ├── __init__.py     # 初期化
    └── ytdc.py         # メインコード
```

#### モードによる違い
| `mode`    | `movie`              | `comment`          | `stats`           |
|-----------|----------------------|--------------------|-------------------|
| `args`で指定 | `start`, `end`, <br>`query`, `channel_id` | `video_id_list` | `video_id_list`   |
| アウトプット    | 動画のメタデータ | 動画のコメント   | 動画の統計量データ  |
|実行タイミング|最初|`movie`実行後|`movie`実行後|
| 保存フォルダ       | `output/movie`     | `output/comment`   | `output/stats` |
| 保存名 (例)      | `キーワード_2010_2010.csv`     | `comment_lastvideoid.csv`   | `stats_lastvideoid.csv`|
| リクエスト数    | `n` 回以上 (※1,2) | `video_id` 回以上 (※1)  | `video_id` 回      |
|1リクエストの消費quota| 100 | 1 | 1 |

※1 再リクエストがない場合のリクエスト数
※2 `n`は、`n`年・`n`月・`n`日と「何単位あるか」を表す


# 最後に
　長くなりましたが、ここまで読んでくださりありがとうございます。
このライブラリが少しでも皆さんのお役に立てると幸いです。もし良かったら記事のいいね等くださると励みになります。

最後に、注意点を述べさせていただきます。 (詳しくは[GitHubコード](https://github.com/momijiro/youtube_data_collector)に記載)
- 本コードは、2023年12月時点で実装したものです。必要に応じて最新の情報を確認してください。([公式サイト](https://developers.google.com/youtube/v3/getting-started?hl=ja))
- APIキーの取得・本ライブラリの使用等による損失・損害については、一切責任を負いかねますので、公式の情報を確認しつつ自己責任で行ってください。
- 問題・不明点等ありましたら、お気軽にお問い合わせください。

ここまでお付き合いいただきありがとうございました！ 
連絡先: [X(Twitter)](https://twitter.com/kanure24)