Youtube Data APIでジャルジャルタワーのメタデータを収集してみた

## はじめに

データ分析をしていると、いろいろな問題が出てきます。なかでも、データを取得する部分でつまずくケースも多いのではないでしょうか？最近ではオープンデータも多く、データ分析しやすい環境も整っています。その一方で、興味のあるデータや自分の趣味に関するデータが見つからないなんてこともあります。

そこで本記事では、

- そもそもデータが無い
- サンプルデータはつまらない
- 自分の興味のあるデータを分析したい
- **Youtubeでジャルジャルタワーをみることが好き**

といったような方々を対象に、Youtubeの再生リストから動画のメタデータを収集する方法について解説します。

なお、2021年12月現在、QiitaでYoutube Data APIと検索すると1,089件ヒットします。
文字通り千番煎じですので、Youtube Data APIに関する説明は以下の記事をご覧ください。

- [YouTube Data APIの始め方](https://qiita.com/TRO555/items/677606b5e2c026cf4838)

### ジャルジャルタワーとは

[ジャルジャルタワー](https://www.youtube.com/user/comtekaigi/featured)とは、お笑いコンビ「ジャルジャル」が運営するYoutubeチャンネルです。
特に[「ネタのタネ」](https://www.youtube.com/playlist?list=PLRdiaanKAFQliJh8AMvlV6t7NBrmNXCo-)シリーズでは3-10分程度のネタを**毎日投稿**しています。
動画のタイトルは「〇〇な奴」となっていることが特徴です。

例：[「悪魔の笑い方のせいで、バイト面接落ちる奴」](https://www.youtube.com/watch?v=1JJNBzpG75g&list=PLRdiaanKAFQliJh8AMvlV6t7NBrmNXCo-&ab_channel=%E3%82%B8%E3%83%A3%E3%83%AB%E3%82%B8%E3%83%A3%E3%83%AB%E3%82%BF%E3%83%AF%E3%83%BCJARUJARUTOWER)[「机食べる奴」](https://www.youtube.com/watch?v=2-dIAiguswQ&t=1s&ab_channel=%E3%82%B8%E3%83%A3%E3%83%AB%E3%82%B8%E3%83%A3%E3%83%AB%E3%82%BF%E3%83%AF%E3%83%BCJARUJARUTOWER)

2021年12月現在、ネタのタネシリーズは**1,400本**を超えており、人手で収集するのは非常に困難です。
本記事ではこのシリーズの

- タイトルが特徴的である
- 動画の数が多い

などの特徴に着目し、メタデータの収集対象としています。

## メタデータの収集

GitHubリポジトリ：https://github.com/kanta-nakamura/jarujaru-tower-crawler

### 環境

- macOS Monterey 12.0.1
- Python 3.9.9

```txt:requirements.txt
cachetools==4.2.4
certifi==2021.10.8
charset-normalizer==2.0.9
google-api-core==2.3.2
google-api-python-client==2.33.0
google-auth==2.3.3
google-auth-httplib2==0.1.0
googleapis-common-protos==1.54.0
httplib2==0.20.2
idna==3.3
protobuf==3.19.1
pyasn1==0.4.8
pyasn1-modules==0.2.8
pyparsing==3.0.6
requests==2.26.0
rsa==4.8
six==1.16.0
uritemplate==4.1.1
urllib3==1.26.7
```

### 取得するメタデータ一覧

|パラメータ|内容|
|---|---|
|video_id|YouTubeが動画を一意に識別するために使用するID|
|published_at|動画がアップロードされた日時<br>値はISO8601（YYYY-MM-DDThh：mm：ss.sZ）形式で指定|
|title|動画のタイトル|
|comment_count|動画のコメント数|
|view_count|動画の再生数|
|like_count|動画のlike数|
|duration|動画の長さ|

### 実装

```python:jarujaru-tower-crawler.py
import os
import time
from apiclient.discovery import build

YOUTUBE_API_KEY = os.environ['YOUTUBE_API_KEY']
JARUJARU_TOWER_PLAYLIST_ID = 'PLRdiaanKAFQliJh8AMvlV6t7NBrmNXCo-'

youtube = build('youtube', 'v3', developerKey = YOUTUBE_API_KEY)

next_page_token = None

print('video_id,published_at,title,comment_count,view_count,like_count,duration')

while True:
    playlist_items_response = youtube.playlistItems().list(
        part='snippet',
        playlistId=JARUJARU_TOWER_PLAYLIST_ID,
        maxResults=50,
        pageToken=next_page_token
    ).execute()

    for i in range(len(playlist_items_response['items'])):
        video_id = playlist_items_response['items'][i]['snippet']['resourceId']['videoId']

        video_response = youtube.videos().list(
            part=['snippet', 'statistics', 'contentDetails'],
            id=video_id
        ).execute()
        
        if len(video_response['items']) > 0:
            published_at = video_response['items'][0]['snippet']['publishedAt']
            title = video_response['items'][0]['snippet']['title']
            comment_count = video_response['items'][0]['statistics']['commentCount']
            view_count = video_response['items'][0]['statistics']['viewCount']
            like_count = video_response['items'][0]['statistics']['likeCount']
            duration = video_response['items'][0]['contentDetails']['duration']

            values = [video_id
                    ,published_at
                    ,title
                    ,comment_count
                    ,view_count
                    ,like_count
                    ,duration]
            
            print(','.join(values))

        time.sleep(3)

    if 'nextPageToken' in playlist_items_response.keys():
        next_page_token = playlist_items_response['nextPageToken']
    else:
        break

    time.sleep(3)
```

### 解説

```python:jarujaru-tower-crawler.py
JARUJARU_TOWER_PLAYLIST_ID = 'PLRdiaanKAFQliJh8AMvlV6t7NBrmNXCo-'
```

ここではジャルジャルタワーのプレイリストIDを指定していますが、任意のプレイリストIDに変更可能です。
プレイリストIDは、URLの`playlist?list=`以下に記載されています。
例：`https://www.youtube.com/playlist?list=[プレイリストID]`

```python:jarujaru-tower-crawler.py
while True:
    playlist_items_response = youtube.playlistItems().list(
        part='snippet',
        playlistId=JARUJARU_TOWER_PLAYLIST_ID,
        maxResults=50,
        pageToken=next_page_token
    ).execute()
```

この部分でAPIを叩いています。
`maxResults`は1回のリクエストで取得する動画の数を指定しており、最大値の`50`を設定しています。


```python:jarujaru-tower-crawler.py
for i in range(len(playlist_items_response['items'])):
        video_id = playlist_items_response['items'][i]['snippet']['resourceId']['videoId']

        video_response = youtube.videos().list(
            part=['snippet', 'statistics', 'contentDetails'],
            id=video_id
        ).execute()
```

この部分では再生リストの各動画のメタデータを取得しています。

```python:jarujaru-tower-crawler.py
if len(video_response['items']) > 0:
            published_at = video_response['items'][0]['snippet']['publishedAt']
            title = video_response['items'][0]['snippet']['title']
            comment_count = video_response['items'][0]['statistics']['commentCount']
            view_count = video_response['items'][0]['statistics']['viewCount']
            like_count = video_response['items'][0]['statistics']['likeCount']
            duration = video_response['items'][0]['contentDetails']['duration']

            values = [video_id
                    ,published_at
                    ,title
                    ,comment_count
                    ,view_count
                    ,like_count
                    ,duration]

            print(','.join(values))
```

各パラメータを取得しています。その他取得可能な値を参照するには[公式ドキュメント](https://developers.google.com/resources/api-libraries/documentation/youtube/v3/python/latest/youtube_v3.videos.html#list)をご参照ください。

```python:jarujaru-tower-crawler.py
if 'nextPageToken' in playlist_items_response.keys():
        next_page_token = playlist_items_response['nextPageToken']
    else:
        break
```

次のページがあればそのページトークンを取得します。

### 実行方法

1. [YouTube Data APIの始め方](https://qiita.com/TRO555/items/677606b5e2c026cf4838)を参考に、youtubeのAPIキーを取得してください。

2. 以下のコマンドを実行

```zsh:zsh
$ brew install forego
$ pip install -r requirements.txt
$ echo "YOUTUBE_API_KEY=[youtubeのAPIキー]" > .env
$ forego run python jarujaru-tower-crawler.py > output.csv
```

無事にメタデータを収集できました！

```csv:output.csv
video_id,published_at,title,comment_count,view_count,like_count,duration
1JJNBzpG75g,2021-12-19T09:00:01Z,『悪魔の笑い方のせいで、バイト面接落ちる奴』ジャルジャルのネタのタネ【JARUJARUTOWER】,430,200754,4435,PT8M6S
IK_z0D8TSsU,2021-12-18T09:00:15Z,『そりゃ逮捕される奴』ジャルジャルのネタのタネ【JARUJARUTOWER】,371,140585,3287,PT4M24S
AYdy2MGLpXY,2021-12-17T09:00:05Z,『友達が大きな決断した瞬間、引く奴』ジャルジャルのネタのタネ【JARUJARUTOWER】,318,105343,2263,PT6M49S
bAqe9rfa3xQ,2021-12-16T09:00:13Z,『やっと自分をさらけ出せた奴』ジャルジャルのネタのタネ【JARUJARUTOWER】,260,94685,2305,PT4M1S
9-xWQIgaYlM,2021-12-15T09:00:03Z,『社員旅行で人生が無茶苦茶なった奴』ジャルジャルのネタのタネ【JARUJARUTOWER】,1154,259370,5422,PT17M32S
```

## おわりに

本記事では、Youtubeの再生リストから動画のメタデータを収集する方法について解説しました。今後は収集したデータをもとに、ジャルジャルタワーの動画タイトルを自動生成する機械学習モデルを構築したいとを考えています。

今回がQiita初投稿ということもあり、至らぬ点も多かったと思いますが、コメントやシェアをしていただけると嬉しいです！

## 参考

- [Youtube Data API](https://developers.google.com/youtube/v3/getting-started?hl=ja)
- [YouTube Data APIの始め方](https://qiita.com/TRO555/items/677606b5e2c026cf4838)
- [ジャルジャルタワー JARUJARU TOWER](https://www.youtube.com/user/comtekaigi/featured)