技術メモ

プログラミングとか電子工作とか

YouTubeのSuperChatをGoogle Spredsheetに読み込む(SuperChatEvents: list使用編)

YouTube Live Streaming APIYouTube Data API v3)を利用してスーパーチャット情報をGoogle Spredsheetに出力してみました。
が、結論から言えば実用性が無かったので供養エントリです。なんでダメだったか知りたい人など対象です。
(あとOAuthの勉強の題材探してる人とか)

内容を要約すれば

  • SuperChatEvents: listを利用してGoogle Spredsheetにデータを抽出する方針、実際にココまではできた
  • 上記APIOAuth認証で承認したアカウントのスーパーチャットを抽出できる(第三者のスーパーチャットは取得できない)
  • 最新50件のみ取得可 ← コレが問題

という感じです。
実用的なのは検証中(クォータ割り当て上限の引き上げは現在やりとり中・・・)

前提

HTMLのパースをしないワケ

結構スーパーチャットを抽出するツールは有志の方々によって開発されています。
ただし、大体YouTubeのチャット欄のHTMLをパースして抽出する方針のものが散見されます。
(これはおそらくなのですが、どっかのバージョンアップまでチャット情報を取得するAPIが無かったのにも起因している可能性はあります)
僕個人としてはYouTube側がしっかりしたツールを用意していない方が問題だと思っているのでいちいち指摘したくないんですが、これはYouTubeの規約に抵触する可能性があります。

利用規約に以下の行為は禁止するという下記のような記載があります。

本サービスの利用には制限があり、以下の行為が禁止されています。
[省略]
3. 自動化された手段(ロボット、ボットネット、スクレーパなど)を使用して本サービスにアクセスすること。ただし、(a)公開されている検索エンジンYouTuberobots.txt ファイルに従って使用する場合、または(b)YouTube が事前に書面で許可している場合を除きます。

www.youtube.com

じゃあ実行タイミングが手動ならええんか?という規約の穴を突くような発想もしたくなりますが、意図としては「負荷増えるからAPI以外でのスクレイピングすんな」だと思うので

の3択が考えられます。
2番目は過去に盥回しにされた人を観測していた経験があり、3番目はアレなので1番目の方針で考えましょう。

なんでスプレッドシート+JS?

非エンジニアの方でも比較的使いやすいスプレッドーシートの拡張機能として実装した方が役に立つかなぁと思った次第です。
TypeScriptに脳を侵された人間なので純JavaScriptみたいな言語は非常に辛いのですが、この規模ならどんな言語でもヨシとします。

実装

流れ

  1. OAuth認証の前準備をしておく(一番最初に書くけど別タイミングにする)
  2. スプレッドシートを作成する
  3. スクリプトを追加する
  4. スクリプトを書く
  5. OAuth認証を行う
  6. 実行する

OAuth認証の前準備をしておく

基本的にこの辺を参照して下さい。もしかしたら古くなってるかも。

www.tech-note.info

ただし、上記の準備では不十分です。不十分な部分は後ほど解説します。

スプレッドシートを作成する

とりあえずスプレッドシートを作成しないとなにも始まらないので作成します。
スプレッドシートのコンソールから新規作成します。

https://docs.google.com/spreadsheets/?usp=mkt_sheets

とりあえず「無題のスプレッドシート」という箇所に何かファイル名を入れておいて保存しておきます。
名前を適当に入れたら勝手に保存されます。

f:id:ysmn_deus:20201019115600p:plain

f:id:ysmn_deus:20201019115904p:plain

スクリプトを追加する

「ツール」→「スクリプトエディタ」を選択するとスプレッドシートに紐付いたスクリプトが作成されます。

f:id:ysmn_deus:20201019120201p:plain

先ほどと同様に適当に名前は付けておきましょう。

スクリプトを書く

main.gstoken.gsの二種類に分けてますが、1ファイルでも別に動くと思います。

f:id:ysmn_deus:20201019130233p:plain

ファイルを追加するには、左上の「ファイル」→「New」→「スクリプトファイル」で名前を適当に入れます。
main.gsを追加したい場合は「Enter new file name」と書かれた箇所にmainと入れると作成されます。

main.gs

token.gs

OAuth認証を行う

OAuth認証の準備をする(続編)

OAuth認証の前準備をしておくの手順では不十分な箇所をここに来てようやくすすめて行きます。
token.gsにはdoGetという関数が含まれているのですが、これはOAuth認証のリダイレクトで飛ばされた先のウェブアプリケーションになっています。
('ω')。o(????????????)という人は、とりあえず無視して読み進めて下さい。たぶん分かります

OAuth認証を承認するには

  1. Googleの承認画面にアクセスする
  2. 自分の作ったスクリプトGoogleアカウントの機能を利用する(今回はYouTube Data API v3の読み取りのみ)
  3. 戻ってきてアクセストークンを取得する為のいろんなidとかを取得する

という流れがあります。

トークン情報をメモっておくシートを作成する

スプレッドシートトークン情報を保存しておくシートを作成します。
まだ何も書いてない「シート1」の名前を変更するか、新しくシートを作るかして、「token」というシートを作成してください。
そこに、OAuth認証の前準備をしておくで取得した「クライアントID」と「クライアントシークレット」を保存しておきます。

f:id:ysmn_deus:20201019141904p:plain

分かる方は適当な位置で大丈夫ですが、よく分からない人は画像の通りA1~A8に名称(無くても良いんですが分かりやすいので)、B1~B8に該当する情報を入力していきます。
今回はB1に「クライアントID」を、B2に「クライアントシークレット」を入力して下さい。

Googleの承認画面にアクセスする

本来であればこの辺はWebアプリケーションに組み込んで運用するものだと思いますが、いかんせんめんどくさ過ぎるのでURLを生成する関数を実行してURLを取得します。
そしてコレをブラウザにコピペして承認してしまおうという魂胆です。

token.gsを開き、メニューから「公開」→「ウェブアプリケーションとして導入」を選択します。

f:id:ysmn_deus:20201019140050p:plain

すると「Deploy as web app」という表示がでてくるので、特に何も考えずに下にある「Deploy」というボタンを押します。

f:id:ysmn_deus:20201019140234p:plain

初めて実行する際には「このスクリプトスプレッドシートの編集や外部サービスへのアクセス(YouTubeからデータを取ってくる操作)」を許可する必要があります。
一度許可していれば後からは何も言われませんが、上記の「Deploy」を押すと下記の警告が表示されるかと思います。

f:id:ysmn_deus:20201019140455p:plain

「許可を確認」を押します。
自分のアカウントを選択して次に進みます。

f:id:ysmn_deus:20201019174837p:plain

(ここでアプリ名が「test01」になってますが、これはスクリプトの名前(エディタが表示されてるところの左上にあるやつ)です。)

f:id:ysmn_deus:20201019140837p:plain

「このアプリは確認されていません」とヤバそうな表示が出ますがヤバくないです。自分の作ったばっかりのアプリケーションなのでGoogle様による確認が済んでないのは当然です。
進む為に左下の詳細をクリックして進みます。

f:id:ysmn_deus:20201019140847p:plain

f:id:ysmn_deus:20201019141047p:plain

順調にいけば最後にURLが表示されます。このURLをtoken.gsの13行目にあるdeployURLとして保存します。

f:id:ysmn_deus:20201019141217p:plain

例えばURLがhttps://script.google.com/macros/s/hogefuga/execと表示されていれば、token.gsの13行目を下記のように修正します。

const deployURL = "https://script.google.com/macros/s/hogefuga/exec"

ここまで来たら、ツールバーの「関数を選択」という箇所で「makeAccessTokenURL」を選択し、三角アイコンのボタンを押します。

f:id:ysmn_deus:20201019142255p:plain

問題無く実行できれば、準備の段階に作成した「token」というシートの一番下にURLが追記されています。

f:id:ysmn_deus:20201019142409p:plain

早々にアクセスしたくなるのですが今アクセスするとはじかれます。
OAuth認証の前準備をしておくでOAuth画面の作成など行ったと思いますが、同じ画面で先ほどのdeployURLへのリダイレクトを許可します。

f:id:ysmn_deus:20201019142703p:plain

このクライアント名のところをクリックすると変種画面に移動します。

f:id:ysmn_deus:20201019142810p:plain

「承認済みの JavaScript 生成元」という箇所にhttps://script.google.comを、「承認済みのリダイレクト URI」にdeployURLに設定したURLを入力します。
画像では2個URLが入ってますが、1個です。
「保存」を押して完了です。

OAuth認証を行う(トークンを取得する為のcodeの取得)

ここまで来たら、先ほど「makeAccessTokenURL」で作成したURLにアクセスします。

f:id:ysmn_deus:20201019142409p:plain

アクセスすると、先ほど「ウェブアプリケーションとして導入」の時に見たような画面が表示されます。

f:id:ysmn_deus:20201019164028p:plain
国会の黒塗り資料みたいになってるのは許して

OAuthクライアント作成時の名前が表示されており、その下にYouTubeのチャンネル(アカウント)が表示されていると思います。
該当するアカウント(スーパーチャット情報が取得したいアカウント)をクリックして次に進みます。

また見覚えのある画面だと思いますので、同様に処理していきます。

f:id:ysmn_deus:20201019164317p:plain

f:id:ysmn_deus:20201019164359p:plain

ここの承認の際に「YouTubeアカウントの表示」となっている事を確認して下さい。
僕が悪意のある人間で、なにがしか余計なことをするのであれば情報の表示のみならずコンテンツの編集やアカウントの情報変更など全てできる権限を承認させます。
ここでは「表示」とあるので、最悪情報が取られるだけで済みます。それはそれで困りますが、ソースも全部出してるのでどういう処理してるのかは確認して下さい。

f:id:ysmn_deus:20201019164715p:plain

しつこいぐらい承認のステップがありますが、OAuthは簡単にできる反面結構権限が強いです。
このぐらい「ほんまに大丈夫なんか?」と聞かれる行為であるということを肝に据えて開発をしましょう。(自戒を込めて)
「許可」を押して処理完了です。

{"status":"ok"}

と表示されれば処理完了です。

上記の処理の最後でエラーページが表示される

幾つかアカウントを所持してログインしていると、上記の処理の最後でエラーになる事があります。
その場合はそのブラウザを閉じずに、エラーページが表示されているブラウザのURLを確認して下さい。
おそらくパラメータにcodeというものが含まれていると思います。

https://script.google.com/macros/s/hogefuga/exec?code=XXXXXXXXXXXXXXXX&hoge=YYYYYYYYYYYYYYYYYY...

上記のcode=XXXXXXXXXXXXXXXXにあたるXXXXXXXXXXXXXXXXの情報さえあれば問題無いのでもしエラーが表示されてしまった場合はそちらをコピーして下さい。
そして、スプレッドシートで作成した「token」というシートのB3にあたるcodeという箇所に貼り付けて置いて下さい。

OAuth認証を行う(新規トークンの発行)

上記までうまくいっていればあとはそこまで難しい処理では無い筈です。
token.gsgetNewAccessTokenを実行します。

f:id:ysmn_deus:20201019170106p:plain

問題が起こらなければ何事も無かったかの用に処理が終わります。
(codeを生成して時間がたっているとエラーが発生するかも知れません)
スプレッドシートtokenのシートにrefresh_tokenなどが生成されているのを確認しておきましょう。

f:id:ysmn_deus:20201019170507p:plain

トークンが生成されていれば、後はこのtoken.gsを直接触ることは無いかと思います。

実行する

それではとりあえず実行してみます。
取得する関数はgetSuperChatEventsとして宣言しています。getSuperChatEventsを実行して下さい。

f:id:ysmn_deus:20201019171230p:plain

問題無ければtokenを作成していたスプレッドシートに実行時間の名前がついたシートが追加されていると思います。

f:id:ysmn_deus:20201019171429p:plain
収益化もされてないアカウントで実行してるのでなにも表示されていない

スーパーチャットが有効化されていて何件か取得できる場合はこのようになります。

f:id:ysmn_deus:20201019172140p:plain

問題点

上記まで実行できれば「おっ、これでスプレッドシートにデータが集約できて便利やな!」という感じなんですが、様々な問題点がありました。
もしかしたら今後APIが改善されるかもしれないので、さしあたり今回用意したスクリプトの意図などを列挙しておきます。

  • SuperChatはアカウント(チャンネル)に対して発生するイベントであり、どのライブで発生したものかは現段階では判別できない
  • SuperChatEvents: listは最新のSuperChatを取得するAPIなので特定期限~現在まで、という縛りでシートに書き出す仕様にした
    • 全部書き出したいって人はmain.gsの1行目にあるafterDateに格納されている日付をかなり古い日付にすればたぶん大丈夫
  • 一番上でも書いたが最新50件のみ取得可、50件以上古いデータは取得できない。これは実際に観測しましたし、海外のフォーラムなどでも言及がありました
  • 上記の制約込みで考えると、GASの最短実行間隔である1分の中でスーパーチャットが50件未満であれば、ライブ時に1分間隔で実行するトリガーを作成して毎分getSuperChatEventsを実行するというのはできそう
    • ただし、人気ライバーさんの記念放送なんてのは1分間に50件以上なんて余裕で来てそうなのでむり
    • 仮に非同期処理で5秒間隔などでgetSuperChatEventsを実行しまくる策も無くは無さそうだが、先にGASのなにがしかの実行制限に到達してしまいそう
    • GCPの有料アカウントで実行することも考えられるが金払うならインスタンス立ち上げて実行しまくった方が確実

今後の課題

たぶんYouTube Live Streaming APIのチャットを取得するAPIを利用してスーパーチャットのみを抽出するのが確実と思われます。
ただし、このAPIライブ配信時に取得し続ける方針は同時接続人数5000~6000ぐらいの状況下で1分あたりのクオータコストが60ぐらいでした。
1アカウントに割り当てられた日にちの上限は10000なので、この規模のライバーさんの放送だと2.7時間が限度という事になります。 実用的で無いこともないんですが、コメント数が増えればクオータコストが上がる可能性がある(こちらは機会があれば別記事で紹介します)ので心許ない気がします。

ちなみに、SuperChatEvents: listのコストは直接分からないんですがたぶん1か2です。チャットを全部取得するよりはコストが低いので可能性としてはこちらを3秒に1回実行する(16件/秒程度のスパチャ速度まで捌ける、一日MAX8時間程度)のが現実的かもしれません。