YouTube Data API を使って自分のチャンネルに関するデータを集計してみた

はじめに

テントの中から失礼します、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 v3

取得・集計するデータ

今回は下記のデータを取得・集計しようと思います。

  • 動画数
  • 総視聴回数
  • チャンネル登録者数
  • 総高評価数
  • 総低評価数
  • 総配信時間

実装

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 には、基本的に partfileds パラメータを付けてリクエストをします。ざっくり説明すると、part には取得したいデータの種別を指定して、fields では part で指定したデータの種別から更に必要なデータのみフィルタできるといった感じになります。

それぞれのパラメータについての詳細は下記を参考にしてください。

チャンネル情報を取得する

では、自分のチャンネル情報について取得する処理を実装します。下記のドキュメントを参考にしています。

チャンネルのリストを取得する際に、フィルタとして 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 を取得する処理を実装していきます。下記のドキュメントを参考にしています。

Search は動画を検索するための機能ですが、forMine を True にすることで、自分が投稿した動画を取得することができます。必要なデータは動画の ID だけなので、partid のみを指定しています。

尚、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

投稿した動画のデータを取得する

では、投稿した動画のデータを取得していきます。下記のドキュメントを参考にしています。

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 かなにかを作りたいな〜なんて考えています。そのうち実現できたらいいなと。

今回は以上になります。最後まで読んで頂きありがとうございました!