この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
テントの中から失礼します、CX事業本部のてんとタカハシです!
以前、下記の記事で、私の YouTube チャンネルに関するデータの集計結果を記載しました。
その際、YouTube Data API を使って、データの集計を行いました、今回は YouTube Data API を使って、自分の YouTube チャンネルに関するデータを取得・集計する方法について記事にしようと思います。
ソースコードは下記のリポジトリに置いています。
GitHub - iam326/youtube-my-channel
前提
- 自分の YouTube チャンネルを持っていること
- YouTube Data API を使用するために必要な認証情報が作成済みであること
認証情報を作成する手順については、下記の記事を参考にしてください。また、作成した認証情報のファイルは client_secrets.json
にリネームして、これから実装していくプログラムのファイルと同じディレクトリに格納してください。
環境
今回は Python を使って、YouTube Data API を叩きます。
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.6
BuildVersion: 18G103
$ python --version
Python 3.9.0
$ pip --version
pip 20.2.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
必要なパッケージのインストール
$ pip install google-api-python-client
$ pip install oauth2client
$ pip install httplib2
$ pip install isodate
google-api-python-client
を使って API を叩きます。ドキュメントは下記になります。
取得・集計するデータ
今回は下記のデータを取得・集計しようと思います。
- 動画数
- 総視聴回数
- チャンネル登録者数
- 総高評価数
- 総低評価数
- 総配信時間
実装
YouTube Data API をラップするモジュール youtube_data_api_client.py
を作成します。まずは、このモジュールに必要な機能を実装していきます。
API クライアントを取得する
YouTube Data API のドキュメントにある サンプルコード を参考にして、API クライアントを取得する処理を実装します。認証情報ファイルのパスと、スコープ については引数で渡せるようにしています。
youtube_data_api_client.py
#!/usr/bin/env python3
import os
import httplib2
from apiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import run_flow
YOUTUBE_API_SERVICE_NAME = 'youtube'
YOUTUBE_API_VERSION = 'v3'
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:
%s
with information from the API Console
https://console.developers.google.com/
For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
"""
class YoutubeDataApiClient():
def __init__(self, client_secrets_file, scopes):
self.__client = self.get_youtube_data_api_client(
client_secrets_file, scopes)
def get_youtube_data_api_client(self, client_secrets_file, scopes):
message = MISSING_CLIENT_SECRETS_MESSAGE % os.path.abspath(
os.path.join(os.path.dirname(__file__), client_secrets_file))
flow = flow_from_clientsecrets(client_secrets_file,
scope=scopes,
message=message)
storage = Storage('youtube-oauth2.json')
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = run_flow(flow, storage)
return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
http=credentials.authorize(httplib2.Http()))
API でデータを取得する際の補足
ここから、YouTube Data API を叩いて自分のチャンネルに関するデータを取得していきます。
各 API には、基本的に part
と fileds
パラメータを付けてリクエストをします。ざっくり説明すると、part
には取得したいデータの種別を指定して、fields
では part
で指定したデータの種別から更に必要なデータのみフィルタできるといった感じになります。
それぞれのパラメータについての詳細は下記を参考にしてください。
チャンネル情報を取得する
では、自分のチャンネル情報について取得する処理を実装します。下記のドキュメントを参考にしています。
- YouTube Data API - Channels: list
- google-api-python-client: YouTube Data API v3 . channels
チャンネルのリストを取得する際に、フィルタとして mine
を True にすると、自分が持っているチャンネルのみ取得することができます。
youtube_data_api_client.py
class YoutubeDataApiClient():
...
def get_my_channel(self):
channels = self.__client.channels().list(
part='snippet,statistics',
mine=True,
fields='items(id,snippet(title,description),statistics(videoCount,viewCount,subscriberCount))'
).execute()
channel = channels['items'][0] # チャンネルを1つしか持っていないので、とりあえずの0固定
snippet = channel['snippet']
statistics = channel['statistics']
return {
'id': channel['id'], # チャンネルを一意に識別するための ID
'title': snippet['title'], # チャンネルのタイトル
'description': snippet['description'], # チャンネルの説明
'video_count': statistics['videoCount'], # チャンネルにアップロードされた動画の数
'view_count': statistics['viewCount'], # チャンネルの視聴回数
'subscriber_count': statistics['subscriberCount'], # チャンネルの登録者数
}
今回は一部のデータのみ取得していますが、他にも様々なデータを取得することが可能です。
YouTube Data API - Channels プロパティ
投稿した全動画の ID を取得する
次に、投稿した動画のデータを取得していきます。投稿した動画のデータを取得する場合は、事前に動画の ID を知っている必要があります。そのため、まずは自分が投稿した全動画の ID を取得する処理を実装していきます。下記のドキュメントを参考にしています。
- YouTube Data API - Search: list
- google-api-python-client: YouTube Data API v3 . search
Search
は動画を検索するための機能ですが、forMine
を True にすることで、自分が投稿した動画を取得することができます。必要なデータは動画の ID だけなので、part
は id
のみを指定しています。
尚、1回のリクエストで取得できるデータには限りがあり、最大が50になります。51本以上動画を投稿している場合は、必要な数だけリクエストを再送する必要があります。その場合は、list_next
メソッドを使用して、1つ前のリクエスト & レスポンスを引数に渡すことで、次のデータを取得することができます。
youtube_data_api_client.py
class YoutubeDataApiClient():
...
def get_my_video_ids(self):
search_list_request = self.__client.search().list(
part='id',
forMine=True,
type='video',
order='date',
maxResults=50,
fields='nextPageToken,items(id(videoId))'
)
video_ids = []
while search_list_request: # 全てのデータが取得できるまでリクエストを投げる
search_list_response = search_list_request.execute()
for video in search_list_response['items']:
video_ids.append(video['id']['videoId'])
search_list_request = self.__client.search().list_next(
previous_request=search_list_request,
previous_response=search_list_response)
return video_ids
投稿した動画のデータを取得する
では、投稿した動画のデータを取得していきます。下記のドキュメントを参考にしています。
- YouTube Data API - Videos: list
- google-api-python-client: YouTube Data API v3 . videos
Videos
で動画のデータを取得する場合、動画の ID をカンマ区切りで最大50個指定することができます。51以上のデータを取得するケースに対応するため、__chunks
というメソッドを別途用意して、引数で指定された動画の ID 配列 video_ids
の中身を50個ずつ分割するようにしています。
また、レスポンスに含まれる duration
は動画の長さを表すのですが、PT#M#S
形式になっていて扱いづらいため、isodate
を使って単純な秒数に変換しています。
youtube_data_api_client.py
import isodate
...
class YoutubeDataApiClient():
...
def get_videos(self, video_ids):
videos = []
for ids in self.__chunks(video_ids, 50): # 配列 video_ids の中身を50個ずつに分割する
videos_list = self.__client.videos().list(
id=','.join(ids),
part='snippet,contentDetails,statistics',
fields='items(id,snippet(title,description,publishedAt),contentDetails(duration),statistics(viewCount,likeCount,dislikeCount,commentCount))'
).execute()
for item in videos_list['items']:
snippet = item['snippet']
details = item['contentDetails']
statistics = item['statistics']
# https://stackoverflow.com/a/16743442
duration = isodate.parse_duration(details['duration'])
videos.append({
'id': item['id'], # 動画を一意に識別するための ID
'title': snippet['title'], # 動画のタイトル
'description': snippet['description'], # 動画の説明
'published_at': snippet['publishedAt'], # 動画のアップロード日時
'duration': int(duration.total_seconds()), # 動画の長さ。API が PT#M#S 形式で返すので、ここでは単純な秒数に変換している
'view_count': int(statistics['viewCount']), # 動画が視聴回数
'like_count': int(statistics['likeCount']), # 高評価の数
'dislike_count': int(statistics['dislikeCount']), # 低評価の数
'comment_count': statistics['commentCount'] # 動画に対するコメントの数
})
return videos
def __chunks(self, l, n):
# https://stackoverflow.com/a/312464
for i in range(0, len(l), n):
yield l[i:i + n]
今回は一部のデータのみ取得していますが、他にも様々なデータを取得することが可能です。
YouTube Data API - Videos プロパティ
データを集計する
では、YouTube Data API を叩くために用意した上記のモジュールを使ってデータを集計していきます。main.py
にコードを書いていきます。
main.py
#!/usr/bin/env python3
import math
from youtube_data_api_client import YoutubeDataApiClient
YOUTUBE_DATA_CLIENT_SECRETS_FILE = "client_secrets.json"
YOUTUBE_DATA_API_CLIENT_SCOPES = [
'https://www.googleapis.com/auth/youtube.readonly']
def main():
youtube = YoutubeDataApiClient(
YOUTUBE_DATA_CLIENT_SECRETS_FILE, YOUTUBE_DATA_API_CLIENT_SCOPES)
channel = youtube.get_my_channel()
video_ids = youtube.get_my_video_ids()
videos = youtube.get_videos(video_ids)
total = {
'duration': 0, # 総配信秒数
'like_count': 0, # 総高評価数
'dislike_count': 0 # 総低評価数
}
for video in videos:
total['duration'] += video['duration']
total['like_count'] += video['like_count']
total['dislike_count'] += video['dislike_count']
total_hours = total['duration'] / 60 / 60
print(channel['title'])
print('配信回数:', channel['video_count'])
print('総視聴回数:', channel['view_count'])
print('チャンネル登録者数:', channel['subscriber_count'])
print('総高評価数:', total['like_count'])
print('総低評価数:', total['dislike_count'])
print('総配信時間:', math.floor(total_hours))
if __name__ == '__main__':
main()
実行結果
こんな感じになります。よくできました。あれ、低評価増えてんな。ぴえん。
$ python main.py
てんとのなかでおべんきょう
動画数: 125
総視聴回数: 2131
チャンネル登録者数: 26
総高評価数: 102
総低評価数: 3
総配信時間: 314
おわりに
と、こんな感じでデータを取得できるので、ライブ配信者としては色々遊べて楽しいです。YouTube 上で見れるチャンネルのアナリティクスも見てて面白いですが、個人的に欲しいデータが見れなかったりもするので、その辺をまとめた My Dashboard かなにかを作りたいな〜なんて考えています。そのうち実現できたらいいなと。
今回は以上になります。最後まで読んで頂きありがとうございました!