YouTuberマイニング #1

YouTubeとYouTuberが好きです。
本記事は、自分を含むYouTuberファンがなぜ好きになるのかを解析するためのデータ分析を行う記事です。
これはシリーズ的に更新していきます。

## この記事でやったこと
- YouTube Data APIでChannelから情報を取得する方法を試す
- 取得した情報をDataFrame(pandas)に格納する

<img width="80%" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/264359/f7215401-a1ee-374c-555d-b53c5d6b173d.png">

上の画像は可愛い女性YouTuber "ゆきりぬ"さんの[チャンネル](https://www.youtube.com/channel/UCMsuwHzQPFMDtHaoR7_HDxg)↓から取得したデータ。
<img width="50%" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/264359/2040dba4-0095-1db5-0953-5e108e41fea3.png">


## コードと解説
コードここにある
[haradai1262/Notebooks-for-youtube-api-usage](https://github.com/haradai1262/Notebooks-for-youtube-api-usage)


### 1. YouTube Data APIとの接続
```python
import sys

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.tools import argparser

import devkey
DEVELOPER_KEY = devkey.api
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
CHANNEL_ID = 'UCMsuwHzQPFMDtHaoR7_HDxg' # channel id of japanese popular (and cute) youtuber "Yukirinu"

# connection build
YT = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=DEVELOPER_KEY)
```
こちらはYouTubeのAPIと接続するためのコードです。
'DEVELOPER_KEY'は自分で取得する必要があるので注意。
[YouTube Data API v3の概要](https://developers.google.com/youtube/v3/getting-started?hl=ja)
[DEVELOPER_KEYの取得方法](https://developers.google.com/youtube/registering_an_application?hl=ja)

CHANNEL_IDは、チャンネルのURLが"https://www.youtube.com/channel/UCMsuwHzQPFMDtHaoR7_HDxg" の場合は、"UCMsuwHzQPFMDtHaoR7_HDxg"です。

### 2. チャンネルの動画リストを取得
```python
def get_channel_vlist( yt, cid, max_num ):
    channel_videos_tmp = []
    feed = yt.search().list( channelId=cid, maxResults=1, order='date', type='video', part='id' ).execute()
    nextPageToken = feed[ 'nextPageToken' ]
    video_idx = 1
    while 1:
        if video_idx > max_num: break
        video_idx += 1
        if not 'nextPageToken' in feed: break 
        nextPageToken = feed[ 'nextPageToken' ]
        vid = feed.get('items')[0]['id']['videoId']
        channel_videos_tmp.append( vid )
        feed = yt.search().list( channelId=cid, maxResults=1, order='date', type='video', part='id', pageToken = nextPageToken ).execute()
    return channel_videos_tmp

channel_videos = get_channel_vlist( YT, CHANNEL_ID, 10 )
```
こちらでは、CHANNNEL_IDから投稿動画をIDを取得します。
なお、APIの仕様上?、このコードだと最大500件程度しか取得できません。
※ うまいことスクレイピングすれば、すべて取得できるかと思います。timestamp確認して複数回実行するとか...



### 3. 動画リストから各動画の情報を取得
```py
def get_video_detail( vid ):
    video_detail = YT.videos().list(part="id,snippet,statistics,contentDetails,topicDetails",id=vid).execute()
    return video_detail.get("items",[])[0]

vlist_details = [ get_video_detail( i ) for i in channel_videos ]    
channel_video_info = {} # { idx : video_details(dictionary) }
for i, v_detail in enumerate(vlist_details):
    channel_video_info[i] = v_detail
```
こちらでは先ほど取得した動画IDのリストから各動画の詳細を取得しています(JSON形式)。
YouTube Data APIでは、タイトル・タグ・説明文や視聴数・いいね数などの統計値など様々な情報が取得できます。
こちらのコードでは、"part="id,snippet,statistics,contentDetails,topicDetails"で取得する情報を選択しています。
取得可能な情報の詳細は以下に記載されています。
[Videos: list &nbsp;|&nbsp; YouTube Data API (v3)](https://developers.google.com/youtube/v3/docs/videos/list?hl=ja)

### 4. 取得した動画情報をデータフレーム化
```py
info_tree = {
    'id': None,
    'snippet': ['title','description','liveBroadcastContent','tags','publishedAt','thumbnails'],
    'statistics': ['viewCount','likeCount','favoriteCount','dislikeCount','commentCount'],
    'contentDetails':['caption','definition','dimension','duration','projection'],
    'topicDetails':['TopicIds', 'relevantTopicIds'],
}

df_cols = []
for parent, child in info_tree.items():
    if child == None: df_cols.append( parent )
    else:
        for c in child: df_cols.append( c )

rows = []
for i, v in channel_video_info.items():
    row = []
    for parent, child in info_tree.items():
        if child == None: row.append( v[parent] )
        elif parent == 'snippet':
            for c in child:
                if c == 'thumbnails':
                    row.append( v[parent][c]['default']['url'] )
                elif c == 'tags':
                    if not 'tags' in v['snippet']: row.append( None )
                    else: row.append( v[parent][c] )
                else:
                    row.append( v[parent][c] )
        elif parent == 'topicDetails':
            if 'topicDetails' in v:
                for c in child:
                    if c in v[parent]: row.append( v[parent][c] )
                    else: row.append( None )
            else:
                row.append( None )
                row.append( None )
        else:
            for c in child: row.append( v[parent][c] )
    rows.append( row )
```
こちらでは、取得した動画の情報をDataFramenに格納するために整理しています。
JSONで取得されている各データを１行のレコードにするために色々しているんですが、結果ごちゃごちゃですね。まぁ動けばいいさ。
※ 最初は綺麗だったんですが、例外処理(topicIdがないデータがある、tagsがないデータがある、など)を追加しているとめっちゃ汚くなりました。いつか整理します...

```py
import pandas as pd
df = pd.DataFrame( rows, columns=df_cols )
print( df.shape )
df.head()
```
<img width="80%" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/264359/f7215401-a1ee-374c-555d-b53c5d6b173d.png">

最後にデータフレームに格納して終わりです。
いい感じになりました。

取得したデータを使っての分析は#2で

### つぶやき
- YouTuberのデータセット公開してみたいかも、有名YouTuberのリスト欲しいからスクレイピングに適当なサイトあれば知りたい
- 簡単なところで、チャンネル登録者数に対する動画の視聴数やいいね(Like)数でファンの熱量みたいなものを分析できる
- こんなことやってみたら？みたいな要望お待ちしております！