YouTube Data api v3をPythonから使って特定のチャンネルの動画を取得する

# 何をするか
タイトルの通り、`YouTube Data api v3`を利用して、特定のチャンネルの動画を取得します。
なお、[参考記事](https://qiita.com/yuji_saito/items/8f472dcd785c1fadf666)に書かれている`publishedAfter`等のパラメータをいじってまで全部の動画を取得はしません。
あるチャンネルの動画を500件くらい欲しいなーと思った時があったので作りました。

`API_KEY`はgoogle developer consoleから取得し、環境変数にいれて使用します。
取得の方法については[google - 承認の認証情報を取得する](https://developers.google.com/youtube/registering_an_application?hl=ja)を参照してください。
(Oauthトークンを取得する必要はありません)

# チャンネルIDについて
ブラウザからチャンネルのページに遷移し、`https://www.youtube.com/channel/XXXXXX`の`XXXXXX`の部分を取得するのがほぼ間違いなく楽だと思うのですが、一応スクリプトも置いておきます。
スクリプトを使えば、検索クエリでのチャンネルの一括検索のようなことができるので、そういう用途であれば使い勝手がいいかもしれません。

- `apiclient`(`pip install --upgrade google-api-python-client`で取得)
- `easydict`(`pip install easydict`で取得)

の２つを使用していますが、後者はデフォルトで入っている`argparse`で代用可能です(というよりも`argparse`が主流です)

```python
import os
from easydict import EasyDict as edict
from apiclient.discovery import build
from apiclient.errors import HttpError

API_KEY = os.environ['API_KEY']
API_SERVICE_NAME = "youtube"
API_VERSION = "v3"

youtube = build(API_SERVICE_NAME, API_VERSION, developerKey=API_KEY)

opt = edict()
opt.q = 'ここに検索したいワードを入れる'
opt.max_results = 25

search_response = youtube.search().list(
    q=opt.q,
    part="id,snippet",
    maxResults=opt.max_results
).execute()

channels = []

for search_result in search_response.get("items", []):
    if search_result["id"]["kind"] == "youtube#channel":
        channels.append("%s (%s)" % (search_result["snippet"]["title"],
                                   search_result["id"]["channelId"]))

print("Channels:\n", "\n".join(channels), "\n")
```

# チャンネルの動画を取得する
本題ですが、googleが提供している`apiclient`に含まれている`search.list`メソッドを使用しての取得に手間取りました。
そのため、[StackOverflow - YouTube API to fetch all videos on a channel](https://stackoverflow.com/questions/18953499/youtube-api-to-fetch-all-videos-on-a-channel) を参考にして`requests`から直接リクエストを送るようにしています。



```python
import os
import time
import requests

import pandas as pd


API_KEY = os.environ['API_KEY']
CHANNEL_ID = 'your_searching_channel_id'

base_url = 'https://www.googleapis.com/youtube/v3'
url = base_url + '/search?key=%s&channelId=%s&part=snippet,id&order=date&maxResults=50'
infos = []

while True:
    time.sleep(30)
    response = requests.get(url % (API_KEY, CHANNEL_ID))
    if response.status_code != 200:
        print('エラーで終わり')
        break
    result = response.json()
    infos.extend([
        [item['id']['videoId'], item['snippet']['title'], item['snippet']['description'], item['snippet']['publishedAt']]
        for item in result['items'] if item['id']['kind'] == 'youtube#video'
    ])
    
    if 'nextPageToken' in result.keys():
        if 'pageToken' in url:
            url = url.split('&pageToken')[0]
        url += f'&pageToken={result["nextPageToken"]}'
    else:
        print('正常終了')
        break

videos = pd.DataFrame(infos, columns=['videoId', 'title', 'description', 'publishedAt'])
videos.to_csv('videos.csv', index=None)
```

これで、動画のidとタイトル、説明文と投稿日の`csv`ファイルを吐き出すことができます。

# 参考

- [qiita - YouTubeの特定のチャンネルに紐付く動画を取得する。（YouTube Data API (v3) Search）](https://qiita.com/yuji_saito/items/8f472dcd785c1fadf666)
- [YoutubeAPI - Python コード サンプル](https://developers.google.com/youtube/v3/code_samples/python?hl=ja#search_by_topic)
- [StackOverflow - YouTube API to fetch all videos on a channel](https://stackoverflow.com/questions/18953499/youtube-api-to-fetch-all-videos-on-a-channel)