【python】YoutubeAPIを用いてオーディンション番組動画の情報を取得する

#動機
自分が最近見ているオーディション番組（PRODUCE 101 JAPAN SEASON2）ではyoutubeチャンネルにパフォーマンス等の動画をアップロードしています。再生回数やコメント数などを見れば、誰が人気か把握できるかと思い、YoutubeAPIを用いて動画の情報を取得したいと思います。

本記事と同様の趣旨でtwitterのデータを取得する記事も投稿致しましたので、もし良かったら見てください。
[【python】TwitterAPIを用いてオーディンション番組の投票数を取得する](https://qiita.com/zawakou_dx/items/ae632b2e80c86958055d)

#開発環境
python3.9.0
google-api-core          1.28.0
google-api-python-client 2.6.0
google-auth              1.30.1
google-auth-httplib2     0.1.0
googleapis-common-protos 1.53.0
Mac OS Mojava 10.14.6

#YoutubeAPIを利用する
利用するまでの流れは以下を参考にいたしました。
>https://qiita.com/g-k/items/7c98efe21257afac70e9

APIの仕様については以下を参照致しました。
[APIリファレンス](https://developers.google.com/youtube/v3/docs?hl=ja)

#オーディション番組のチャンネルにアップロードされている動画の情報を取得する
```python
from apiclient.discovery import build

def get_items(self,response):
        for search_result in response.get("items", []):
            if search_result["id"]["kind"] == "youtube#video":
                title=search_result["snippet"]["title"]
                #自作の関数で取得したい動画のタイトルをチェックする
                #情報を取得しない動画の時はcontinue
                output_str=self.check_title(title)
                if type(output_str) == int:
                    continue
                #videoIdで詳細な動画データ取得
                video_result = self.youtube.videos().list(
                        #リソースプロパティの指定
                        part='statistics',
                        #取得する情報のフィルタリング
                        id=search_result["id"]["videoId"]).execute()

                #再生回数,高評価,低評価,コメント数取得
                result=[]
                statistics=video_result['items'][0]['statistics']
                result.append(output_str)
                result.append(statistics['viewCount'])
                result.append(statistics['likeCount'])
                result.append(statistics['dislikeCount'])
                result.append(statistics['commentCount'])
                videos.append(result)
                self.__total_videos += 1

def video_searcher(self):
   #取得したい動画数
   target_num=65
   #first search
   response = self.youtube.search().list(
                part='id,snippet',
                channelId=CHANNEL_ID,
                order='date',#日付順で取り出す
                type='video',
              ).execute()

    get_items(response)

     #maxResults以上に動画がある場合には次ページに次動画が格納される
     #1ページずつ取得していく
     nextPageToken = response.get("nextPageToken")
     while(target_num > self.__total_videos):
        print(nextPageToken)
        response = self.youtube.search().list(
                        part='id,snippet',
                        channelId=CHANNEL_ID,
                        order='date',
                        type='video',
                        maxResults=5,
                        pageToken=nextPageToken
                        ).execute()
         try:
             nextPageToken = response.get("nextPageToken")
         except:
             break
         self.get_items(response)
```
以下で細かく説明していきます。


```python
response = self.youtube.search().list(
                part='id,snippet',
                channelId=CHANNEL_ID,
                order='date',#日付順で取り出す
                type='video',
              ).execute()
```

まずはチャンネルの動画一覧（以下、リソース）を取得します。
どんな情報が取れるかは以下を参照。
[searchAPIリファレンス](https://developers.google.com/youtube/v3/docs/search?hl=ja)
partに取得したリソースを設定します。
channelIdにはリソースを取得したたチャンネルのIDを入れます。
チャンネルIDは以下の方法で取得しました(2021.5.31)
1.取得したいチャンネルの動画を開く
2.動画からチャンネルのページに飛ぶ
3.URLのchannel/以降の文字列がID
例：https://www.youtube.com/channel/UC-smiHPuMela07NTmpF6hZw
UCから最後まで

>order='data'
type='video'

最新の動画を取得したいのでorderにdateを指定してソート
動画の情報を取得したいのでtypeに指定

```python
nextPageToken = response.get("nextPageToken")
response = self.youtube.search().list(
                        part='id,snippet',
                        channelId=CHANNEL_ID,
                        order='date',
                        type='video',
                        maxResults=5,
                        pageToken=nextPageToken
                        ).execute()
         try:
             nextPageToken = response.get("nextPageToken")
         except:
             break
```

一度に取得する数をmaxResultsで指定します。(デフォルト値5)
リソースはページという単位に格納されています。
maxResults以上の動画をチャンネルから取得する場合には次ページを参照する必要があり、
pageTokenに次ページの情報設定して実行することで次のページが参照可能です。
こうやって次々とリソースを取得していきます。


動画が一覧が取得できたので、各動画の詳細な情報を取得します。

```python
video_result = self.youtube.videos().list(
                        #リソースプロパティの指定
                        part='statistics',
                        #取得する情報のフィルタリング
                        id=search_result["id"]["videoId"]).execute()
```

どんな情報が取れるかは以下を参照。
[videosAPIリファレンス](https://developers.google.com/youtube/v3/docs/videos?hl=ja)
リソースにはstatistics以外にも色々ありますが必要な分だけ取得。出来るだけ不要なリソースは取得しないようにするのが良いと思います。（理由は後で説明）
動画に一意に割り当てられるvideoIdをidに指定します。

```python
statistics=video_result['items'][0]['statistics']
                result.append(output_str)
                result.append(statistics['viewCount'])
                result.append(statistics['likeCount'])
                result.append(statistics['dislikeCount'])
                result.append(statistics['commentCount'])
```

statistics以下の再生回数、コメント数等の情報にアクセスします。

#クォータという概念
youtubeへのリクエストには制限があります。
何回もリクエストを投げると以下のようなエラーが出ます。

>googleapiclient.errors.HttpError: <HttpError 403 when requesting https://youtube.googleapis.com/youtube/v3/search?part=id%2Csnippet&channelId=UC-smiHPuMela07NTmpF6hZw&order=date&type=video&maxResults=5&pageToken=CAUQAA&key=AIzaSyB3bohFevu478iOKQiTc96HuSvwNWwAeaI&alt=json returned "The request cannot be completed because you have exceeded your <a href="/youtube/v3/getting-started#quota">quota</a>.". Details: "[{'message': 'The request cannot be completed because you have exceeded your <a href="/youtube/v3/getting-started#quota">quota</a>.', 'domain': 'youtube.quota', 'reason': 'quotaExceeded'}]">

各ユーザに割り当てられたクォータ量は決まっており、1日の使用量が上限を超えるとリクエストを投げれなくなります。割り当てられたクォータ量は日本時間の17時にリセットされます。
上記のエラーが出ると、次の17時までAPIへリクエストできません。
[クォータについて](https://developers.google.com/youtube/v3/getting-started?hl=ja#quota)

上記の公式ドキュメントを参考にすると、取得するリソースの量によって使用するクォータ量が変わります。極力必要なリソースのみを取得して自身に割り当てられたクォータ上限に達しないよう注意しましょう。
取得するリソースをpart,fieldsパラメータに指定します。
例
>part='snippet,contentDetails,statistics',          fields='items(id,snippet(title,description,publishedAt),contentDetails(duration),statistics(viewCount,likeCount,dislikeCount,commentCount))'

fieldsで指定した値で、partに指定したリソースのフィルタリングを行なっています。

#結果
動画タイトル、再生数、高評価、低評価、コメント数をまとめています。
>タイトル,再生回数,高評価,低評価,コメント数
「Another Day」コンセプトバトル Dance Practice,121341,5755,25,1051
「Goosebumps」コンセプトバトル Dance Practice,197115,8719,56,1579
「A.I.M(Alive In My Imagination)」コンセプトバトル Dance Practice,140623,4661,49,1387
「SHADOW(Slip Inside)」コンセプトバトル Dance Practice,118607,4762,28,1160
「STEP」コンセプトバトル Dance Practice,80237,3467,30,862
「STEP」 Performance No Cut ver.［コンセプトバトル］,94583,3427,42,683
「Another Day」 Performance No Cut ver.［コンセプトバトル］,149222,5576,33,742
「Goosebumps」 Performance No Cut ver.［コンセプトバトル］,206585,6895,85,1066
「SHADOW(Slip Inside)」 Performance No Cut ver. ［コンセプトバトル］,142584,4701,34,952
「A.I.M(Alive In My Imagination)」 Performance No Cut ver.［コンセプトバトル］,196125,4910,86,1255
池﨑 理人,69078,3494,82,626
笹岡 秀旭,29602,1713,21,370
上田 将人,10872,417,118,62
中野 海帆,26510,1762,22,278
西 洸人,65450,3661,140,336
田島 将吾,77573,4384,34,503
西島 蓮汰,40506,2736,23,294
小池 俊司,34836,2275,78,374
福田 翔也,24132,2065,711,586
中野 海帆,38098,2780,32,583
西島 蓮汰,60495,4557,37,408
佐野 雄大,85726,6086,597,1327
木村 柾哉,119577,9877,112,1330
大和田 歩夢,12220,1013,23,198
内田 正紀,7021,1105,13,255
小堀 柊,107393,7963,89,1953
飯沼 アントニー,39404,3094,38,581
小池 俊司,74836,4580,300,1034
四谷 真佑,13510,2275,19,454
篠原 瑞希,15245,1090,66,189
阪本 航紀,23300,1440,965,407
仲村 冬馬,27043,3565,9,605
尾崎 匠海,40402,3588,52,525
村松 健太,18333,1400,975,520
福田 歩汰,10953,1289,53,386
松田 迅,77599,4673,198,931
西 洸人,114960,6759,397,899
テコエ 勇聖,12301,1006,49,211
髙橋 航大,36206,2409,58,507
飯吉 流生,6884,727,23,149
笹岡 秀旭,24899,2229,32,414
井筒 裕太,27537,2676,15,535
松本 旭平,10856,530,38,106
藤牧 京介,104144,9190,47,1180
小林 大悟,79076,5237,75,860
髙塚 大夢,54700,4566,283,847
太田 駿静,21144,3664,20,724
森井 洸陽,17378,1296,37,239
田島 将吾,148634,7426,192,1605
平本 健,20073,1611,14,403
後藤 威尊,65204,4484,45,727
池﨑 理人,43969,3110,160,485
大久保 波留,28362,3561,304,955
ヴァサイェガ 光,11138,1121,44,235
栗田 航兵,13192,2409,59,475
上田 将人,12213,631,386,141
許 豊凡,69498,5357,36,901
寺尾 香信,22978,2214,36,461
\#8 ハイライト｜コンセプトバトル ♫ Another Day パフォーマンス,312891,9740,45,1822
\#8 ハイライト｜コンセプトバトル ♫ A.I.M パフォーマンス,359344,8234,113,2620
\#8 ハイライト｜コンセプトバトル ♫ SHADOW パフォーマンス,350180,8846,55,2111
\#8 ハイライト｜コンセプトバトル ♫ STEP パフォーマンス,262661,7375,74,1560
\#8 ハイライト｜コンセプトバトル ♫ Goosebumps パフォーマンス,497775,12889,188,2248