YouTube APIで遊んでいたらクオータ制限にかかった話

## はじめに

YouTubeチャンネルのデータ（再生数、コメント数、高評価数、投稿時期など）を分析したくて、YouTube Data APIを使って遊んでいたら思わぬ落とし穴にハマった経験を共有します。

## エラーの概要と原因

YouTube Data APIには1日あたり10,000ユニットという制限があります。各APIコールに対して一定のユニットが消費され、1日の合計が制限を超えるとエラー403（quotaExceeded）が発生します。

[公式ドキュメントの割り当て使用量のセクション](https://developers.google.com/youtube/v3/getting-started?hl=ja#quota)より

>割り当て使用量
>YouTube Data API は割り当てを使用して、デベロッパーがサービスを意図したとおりに使用するようにします。また、サービス品質を不当に引き下げたり、他のユーザーのアクセスを制限したりするアプリケーションを作成しないようにしています。無効なリクエストを含むすべての API リクエストには、少なくとも 1 ポイントの割り当て料金が発生します。アプリケーションで使用可能な割り当ては、API Console で確認できます。
>YouTube Data API を有効にしたプロジェクトには、デフォルトで 1 日あたり 10,000 ユニットの割り当てが設定されています。これは、YouTube の API ユーザーの大多数に対して十分な量です。デフォルトの割り当ては変更される可能性がありますが、これは割り当ての配分を最適化し、API ユーザーにとってより意味のある方法でインフラストラクチャをスケーリングするのに役立ちます。割り当ての使用状況は、API Console の [割り当て] ページで確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303979/a86d652c-acb2-4ff8-a5a2-9f75c6206c1b.png)

## やりたかったこと

ももクロの公式YouTubeチャンネルの全動画データを2008年から現在まで収集し、分析できる形で保存することが目標でした。

当初はTwitterでの同様のデータ収集も検討しましたが、API使用料を考慮して断念しました。

## 実装環境

- 言語：Python
- 実行環境：EC2（実行環境として使用）
- データ保存先：S3

※定期実行の予定がなく、一回きりの実行を想定していたため、即効性を重視してシンプルな構成にしました。
※実装の詳細については、以下のGitHubリポジトリをご参照ください：[momoiro-youtube](https://github.com/canta1sei/code_playground/tree/7af190664320648e96954d095a61a85f222b5614/python/momoiro-youtube)


## 実装時に直面した課題

### その1：リスト取得の上限

YouTube APIでは、1回のリクエストで取得できる動画リストの上限が500件でした。
エラーになったわけでもなくそこまで大きな問題にはなっていないですが一応こういう制限もありました、という共有です。

⇒ チャンネルの投稿頻度を考慮し、「年単位で500本も投稿はないだろう」と推測。年単位でのデータ取得に方針を変更しました。

### その2：クオータ制限

基本的な動作確認が完了し、「あとはダウンロードしやすいディレクトリ構成で出力するように整えよう」というタイミングで制限に引っかかりました。~~終わり際でよかった。。~~

```teraterm.log
Processed video 12: あーりん（佐々木彩夏）「AARIN ULTRA REMIX 2017 by DJ KOO」VJ VIDEO
Processed video 13: 【AE限定】ソロコン4タイトルセット映像特典ダイジェスト
Processed video 14: あーりん講座「あーりん相撲」
Processed video 15: 高城れに『まるごとれにちゃん』LIVE Blu-ray &amp; DVD Trailer
An HTTP error 403 occurred: b'{\n  "error": {\n    "code": 403,\n    "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n    "errors": [\n      {\n        "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n        "domain": "youtube.quota",\n        "reason": "quotaExceeded"\n      }\n    ]\n  }\n}\n'

Fetching videos for year 2018
An HTTP error 403 occurred: b'{\n  "error": {\n    "code": 403,\n    "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n    "errors": [\n      {\n        "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n        "domain": "youtube.quota",\n        "reason": "quotaExceeded"\n      }\n    ]\n  }\n}\n'

Fetching videos for year 2019
Processed video 1: 『MOMOIRO CLOVER Z』SHOW at 東京キネマ倶楽部_映像発売記念！  演出家「多田卓也」×振付師「avecoo」×出演者「DragQueen」コメンタリー生配信
Processed video 2: 5th ALBUM『MOMOIRO CLOVER Z』SHOW at 東京キネマ倶楽部_SPOT_Vol.6（ナレーション：DragQueen）
Processed video 3: 5th ALBUM『MOMOIRO CLOVER Z』SHOW at 東京キネマ倶楽部_SPOT_Vol.5（ナレーション：DragQueen）
An HTTP error 403 occurred: b'{\n  "error": {\n    "code": 403,\n    "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n    "errors": [\n      {\n        "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n        "domain": "youtube.quota",\n        "reason": "quotaExceeded"\n      }\n    ]\n  }\n}\n'

Fetching videos for year 2020
An HTTP error 403 occurred: b'{\n  "error": {\n    "code": 403,\n    "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n    "errors": [\n      {\n        "message": "The request cannot be completed because you have exceeded your \\u003ca href=\\"/youtube/v3/getting-started#quota\\"\\u003equota\\u003c/a\\u003e.",\n        "domain": "youtube.quota",\n        "reason": "quotaExceeded"\n      }\n    ]\n  }\n}\n'
```


## 学んだこと

外部APIを利用する際は、以下の点に注意が必要だと実感しました：

- APIの利用制限（クオータ）をあらかじめ確認する
- テスト実行時も本番と同じような量のリクエストを想定する
- 制限に引っかかった場合の対処方法を事前に検討する

## 制限への対処方法

今回は以下の理由で、「明日もう一回実行すれば大丈夫！」という対処を選択しました：

- 本来の目的（データの一括取得）は1回実行できれば十分
- 定期実行の必要性がない
- 翌日には制限がリセットされる

（当日中にどうしても必要な場合はAPIキーを作り直せば回避できそうでした）

## 改善の余地

もっと動画投稿の回数が多いチャンネルでも同様の分析をする場合だったり、動画一つ一つに対して深い分析データが必要になった場合は、以下のような改善が必要になりそうです：

- クオータ制限を考慮したリクエスト制御
- バッチ処理による段階的なデータ取得
- エラーハンドリングの強化
- そもそもローカルの試験はスタブを利用して行い、接続が本当に必要な際に接続テストを行う

## まとめ

外部APIを利用する際は、機能面だけでなく制限事項も意識しておかないと場合によっては痛い目をみると学びました。また、目的に応じて「今の実装で十分か」を判断することも、効率的な開発には必要だと感じました。

## 参考
[YouTube Data API v3 を利用して Google Drive の動画を自動で YouTube にアップロードしてみた](https://qiita.com/Erytheia/items/4aa0fc0599db1233c333)
youtubeAPIの使い方からクオータ制限の話まで詳しく書いてくださっております。（始める前から見ておけばよかったと思っています笑）


[概要-API Reference](https://developers.google.com/youtube/v3/docs?hl=ja)
[YouTube Data API - Errors](https://developers.google.com/youtube/v3/docs/errors?hl=ja#general-errors)
[割り当て使用量](https://developers.google.com/youtube/v3/getting-started?hl=ja#quota)
YouTube Data API 公式ドキュメントです。ユニット数の情報ｍ載っています。