【WebAPI】YouTubeチャンネルを監視してみた

トライアル

この記事は2019年に別サイトへ投稿した記事を一部修正して移行したものです。

概要

YouTubeチャンネルの監視をしてみましょう。
YouTubeチャンネルの動画数や登録者数といった情報を、WebAPIを使って取得します。
いま流行りのWebAPIです。

2022年現在では流行ってないけどね

WebAPIを使うだけでは物足りないので、取得した情報を管理者宛にメール送信したり、Excelファイルへ保存したりしてみようと思います。

学習すること

  • YouTube WebAPIの使い方
  • Pythonによるメール送信の方法
  • PythonによるExcelファイルへの書き込み方法

前提知識

  • Pythonプログラミング

開発環境

  • Python3実行環境(Windows、MacOS、Linux上のPython仮想環境)
    ※当記事ではWindows10を使用します。

開発実施

手順

開発は次の手順で進めます。

  1. APIキーを取得する
    Google Cloud Platform にて YouTube Data API のアクセスキーを取得します。
  2. パラメータの準備をする
    取得したAPIアクセスキー、監視対象のYouTubeチャンネルID、メール送信情報、および出力先Excelファイル名といったパラメータを、実行プログラムが参照できる場所へ設定します。
  3. プログラムを作成する
    YouTubeチェンネルへアクセスして情報を取得し、取得した情報をメール送信し、あわせてExcelファイルへも書き込むといった処理を、Pythonプログラムで作成します。
  4. プログラムをスケジューリングする
    作成したPythonプログラムが定期的に実行されるようにスケジューリングします。
    UNIXの場合は cron、Windowsの場合はタスクスケジューラなどへ設定します。
    ただし当記事では手動実行とします。

では順に進めていきましょう。

APIキーを取得する

一般的に、あるWebサイトに対してWebAPIを使ってアクセスするためには、事前に許可申請して取得したアクセスキーが必要です。YouTubeのWebAPIも同じようにアクセスキーが必要となります。

YouTubeチャンネルへアクセスするためのキー(以降「APIキー」と呼ぶ)は、次の手順で取得します。

  1. Googleアカウントを作成してGoogleへログインする
  2. Google Cloud Platform のConsoleにて新規プロジェクトを作成する
  3. 新規プロジェクトにて、YouTube Data API サービスを有効化しAPIキーを発行する

詳しい手順は割愛するね。
こまかい手順やConsole画面の様子は月日がたつと変わってしまうからね!

パラメータの準備をする

プログラムを実行するときに必要なパラメータを準備します。
今回作成するプログラムでは、以下のパラメータを使います。

#パラメータ設定場所補足説明
1APIキー実行機OSの環境変数YouTubeのWebAPIへアクセスするためのAPIキーです。
環境変数名は何でもよいですが、当記事では “YOUTUBE_DEVELOPER_KEY” とします。
2YouTubeチャンネルIDJSONファイル監視対象となるYouTubeサイトのチャンネルIDです。
JSONファイルは実行機の任意の場所に配置します。当記事ではファイル名を “param_youtube_id.json”とします。
3メール送信情報JSONファイルメール送信情報とは、SMTPホスト名、SMTPポート番号、送信元ユーザ名、送信元アドレス、および送信先アドレスです。
JSONファイルは実行機の任意の場所に配置します。当記事ではファイル名を “param_youtube_mail.json”とします。
4メール送信パスワード実行機OSの環境変数メール送信者がSMTPホストへアクセスするためのパスワードです。
環境変数名は何でもよいですが、当記事では “MAIL_FROM_PW” とします。
5Excelファイル名JSONファイル取得した情報の書き込み先となるExcelファイル名を指定します。当記事では “YouTubeInfo.xlsx” とします。
JSONファイルは実行機の任意の場所に配置します。当記事ではファイル名を “param_youtube_excel.json”とします。

参考までに、これらのパラメータを記載した設定ファイルを事前に作成するプログラムを掲載しておきます。

# 【補足】<> 内は適宜その説明どおりの情報を設定してください。

import json

# パラメータを定義する。
dict_channel_id = {'channel_id': '<アクセスするチャンネルのID>'}
dict_mail = {
                'smtp_host': '<SMTPホスト名>',
                'smtp_port': 587,
                'from_user': '<送信元ユーザ名>',
                'from_addr': '<送信元アドレス(適当でOK)>',
                'to_addr': '<送信先アドレス>'
            }
dict_excel = {'file_name': '<Excelファイル名>'}

# 定義したパラメータをJSONファイルへ書き込む。
with open('<YouTubeチェンネルIDを保存するJSONファイルのフルパス>', 'w') as f:
    json.dump(dict_channel_id, f, indent=4)

with open('<メール送信情報を保存するJSONファイルのフルパス>', 'w') as f:
    json.dump(dict_mail, f, indent=4)

with open('<Excel情報を保存するJSONファイルのフルパス>', 'w') as f:
    json.dump(dict_excel, f, indent=4)

監視プログラムを作成する

Pythonプログラムを機能別に4本作成します。それぞれ別ファイルに分けます。

  • YouTube情報取得クラスを定義するプログラム
  • メール送信クラスを定義するプログラム
  • Excel出力クラスを定義するプログラム
  • 各クラスを呼び出して処理を実行するプログラム

YouTube情報取得クラスの定義は次のとおりです。
取得する項目は、チャンネルタイトル(title)、動画数(videoCount)、登録者数(subscriberCount)、および視聴回数(viewCount)としました。
WebAPIで取得できる情報は他にもたくさんありますが、今回は学習目的のためこの4項目とします。

import os

from googleapiclient.discovery import build

FNAME_PARAM_YOUTUBE_ID = "param_youtube_id.json"


class YouTubeWatcher(object):

    def __init__(self):
        self.developer_key = os.getenv("YOUTUBE_DEVELOPER_KEY")
        self.api_service_name = "youtube"
        self.api_version = "v3"

        # パラメータJSONファイルは当プログラムと同じ場所にあるものとする。
        with open(os.path.join(os.path.dirname(__file__), FNAME_PARAM_YOUTUBE_ID)) as f:
            param = json.load(f)
        self.param = param
        self.channel_id = param["channel_id"]
        self.info = {}

    def watch(self):
        try:
            youtube = build(self.api_service_name,
                            self.api_version,
                            developerKey=self.developer_key
                            )

            response = youtube.channels().list(part="snippet, statistics",
                                                id=self.channel_id).execute()

            self.info["title"] = response["items"][0]["snippet"]["localized"]["title"]
            self.info["id"] = self.channel_id
            self.info["videoCount"] = response["items"][0]["statistics"]["videoCount"]
            self.info["subscriberCount"] = response["items"][0]["statistics"]["subscriberCount"]
            self.info["viewCount"] = response["items"][0]["statistics"]["viewCount"]

        except Exception as e:
            print(f'YouTubeWatcher.watch() Failed. :{e}')
            self.info = None

        return self.info

つづいてメール送信クラスの定義です。

import os
from datetime import datetime

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formatdate

FNAME_PARAM_MAIL = "param_youtube_mail.json"


class Mailer(object):

    def __init__(self):
        self.from_pw = os.getenv("MAIL_FROM_PW")

        # パラメータJSONファイルは当プログラムと同じ場所にあるものとする。
        with open(os.path.join(os.path.dirname(__file__), FNAME_PARAM_MAIL)) as f:
            param = json.load(f)
        self.param = param
        self.smtp_obj = None
        self.smtp_host = param["smtp_host"]
        self.smtp_port = int(param["smtp_port"])
        self.from_user = param["from_user"]
        self.from_addr = param["from_addr"]
        self.to_addr = param["to_addr"]

    def send(self, info):

        # 本文を作成する。
        message = ''
        for k, v in info.items():
            message += str(k) + ': ' + str(v) + '\r\n'
        message += '\r\n\r\n' + formatdate()

        # 件名を作成する。
        subject = "youtube report " + datetime.now().strftime('(%Y.%m.%d %H:%M:%S)')

        # 送信情報を作成する。
        mime = MIMEText(message)
        mime['From'] = self.from_addr
        mime['To'] = self.to_addr
        mime['Subject'] = Header(subject, 'utf-8')

        # 作成したメールを送信する。
        try:
            self.smtp_obj = smtplib.SMTP(self.smtp_host, self.smtp_port)

            # EHLO(Extend Hello)を実行してSMTPサーバへ明示的に身元を明かす。
            self.smtp_obj.ehlo()
            # TLS(Transport Layer Security)に対応している場合は、SMTPコマンドを暗号化する。
            if self.smtp_obj.has_extn('STARTTLS'):
                self.smtp_obj.starttls()

            self.smtp_obj.login(self.from_user, self.from_pw)
            self.smtp_obj.send_message(mime)

        except Exception as e:
            print(f'Mailer.send() Failed. :{e}')

        finally:
            self.smtp_obj.quit()

ひきつづき、Excel出力クラスの定義です。

import os
from datetime import datetime

import openpyxl as excel

FNAME_PARAM_EXCEL = "param_youtube_excel.json"


class Exceler(object):

    def __init__(self):
        # Sheetの1列目を項目名、2列目を項目値とする。
        self.column_item = 1
        self.column_val = 2

        # パラメータJSONファイルは当プログラムと同じ場所にあるものとする。
        with open(os.path.join(os.path.dirname(__file__), FNAME_PARAM_EXCEL)) as f:
            param = json.load(f)
        self.param = param
        self.path_output = os.path.join(os.path.dirname(__file__), param["file_name"])
        self.book = None

    def save(self, info):

        try:
            # YouTubeチャンネル情報を出力するシート名は、出力時の"日付_時刻"とする。
            sheetname = datetime.now().strftime('%Y%m%d_%H%M%S')

            if os.path.exists(self.path_output):
                self.book = excel.load_workbook(self.path_output)
            else:
                self.book = excel.Workbook()

            # シートをブックの先頭へ追加する。
            new_sheet = self.book.create_sheet(title=sheetname, index=0)

            # チャンネルタイトルをシートへ書き込む。
            new_sheet.cell(row=1, column=self.column_item, value="Title")
            new_sheet.cell(row=1, column=self.column_val, value=info["title"])

            # チャンネルIDをシートへ書き込む。
            new_sheet.cell(row=2, column=self.column_item, value="ID")
            new_sheet.cell(row=2, column=self.column_val, value=info["id"])

            # 動画数をシートへ書き込む。
            new_sheet.cell(row=3, column=self.column_item, value="VideoCount")
            new_sheet.cell(row=3, column=self.column_val, value=info["videoCount"])

            # 登録者数をシートへ書き込む。
            new_sheet.cell(row=4, column=self.column_item, value="SubscriberCount")
            new_sheet.cell(row=4, column=self.column_val, value=info["subscriberCount"])

            # 視聴回数をシートへ書き込む。
            new_sheet.cell(row=5, column=self.column_item, value="ViewCount")
            new_sheet.cell(row=5, column=self.column_val, value=info["viewCount"])

            self.book.save(self.path_output)

        except Exception as e:
            print(f'Exceler.save() Failed. :{e}')

        finally:
            self.book.close()

最後に、定義したクラスを生成して実行するプログラムを作成します。

from youtubewatcher import YouTubeWatcher
from mailer import Mailer
from exceler import Exceler


def main():

    # 指定チャンネルの情報を取得する。
    watcher = YouTubeWatcher()
    info = watcher.watch()

    # 取得した情報をメールで送信する。
    mailer = Mailer()
    mailer.send(info)

    # 取得した情報をExcelファイルへ保存する。
    exceler = Exceler()
    exceler.save(info)


if __name__ == "__main__":
    main()

プログラミングは以上です。

プログラムを実行する

監視プログラムは通常スケジューラで定期実行しますが、まずはコマンドプロンプトから手動で実行して動作を確認してみます。

プログラムの実行

python main.py

指定したYouTubeチャンネルの情報を取得し、指定したメールアドレスへ送信され、併せて指定したExcelファイルへ保存されていれば成功です。

諸事情により、実行結果のイメージは割愛するね

ちなみにYouTubeサイトのチャンネルIDは、URLを見れば分かります。
例えばAWSの公式YouTubeサイトの場合、”channel” の後の “UCd6MoB9NC6uYN2grvUNT-Zg” がIDとなります。

【URL】https://www.youtube.com/channel/UCd6MoB9NC6uYN2grvUNT-Zg

もしくはチャンネル情報をスクレイピングして、”items” -> “id” を検索しても取得できます。

課題

今回はここまでですが、実用性を考えるともう少し機能追加が必要であると思われます。

  • パラメータの変更や保存先ファイルを容易にカスタマイズできるようにする。ツールの提供など。
  • 複数チャンネルを監視できるようにする。手動では困難な多数チャンネルの大量データを扱ってこそ自動化の意味がある。
  • 取得した情報をグラフで表示して可視化する。登録者数の増減遷移など。
  • プログラムをスケジューラで定期実行できるようにする。

これらの機能追加はそれなりにボリュームがあるため、改めて別の記事として投稿できればと思っています。

スケジューラによる定期実行について触れなかったのは、実行するOSに依存するためです。
Windowsの場合はタスクスケジューラ、Linux系の場合はcronに設定することになると思いますが、その他サードパーティのスケジューリングアプリを使ってもよいでしょう。
いずれの場合でも、スケジューラに設定するためにはプログラムファイルを事前に実行ファイルへ変換しておく必要があります。
Pythonプログラムの場合は、Pyinstaller等を使用して実行ファイルへ変換できます。
ただしPyinstallerはPython3.6以上であることが条件です。

ちなみにWindowsで作成した実行ファイルはWindowsでしか実行できなくて、
Macで作成した実行ファイルはMacでしか実行できないよ。

実行ファイルってそういうものだけどね。

まとめ

WebAPIを使ってWebサイトの情報を取得してみました。
Google Cloud Platform のConsoleにてAPIキーを申請・発行すれば、YouTubeチャンネルの情報を容易にJSON形式でスクレイピングできることがわかりました。
今回は基本情報の取得だけを行い、ついでにメール送信したりExcelファイルへ保存するといったことを試してみました。

少し前であれば、これくらいのプログラムで十分稼ぐことができたようですが、今ではそうもいかないでしょう。
とはいえ、多くのチャンネルを一括でスクレイピングしたり、取得した情報を可視化したり、さらにはデータ分析などの機能を加えれば、それなりに実務で使えるツールになる可能性はあると思います。

コメント

タイトルとURLをコピーしました