以前、YOUTUBE動画のタイトルとURL、チャンネルを指定して丸ごと取得するをやりました。このときは取得したタイトルとurlはExcelファイルに保存しましたが、今回はGoogle スプレッドシートに表示させます。デスクトップアプリの場合はC#でやればいいのですが、今回はNode.Jsを使います。そしてPuppeteerというライブラリを使います。

HerokuでPuppeteerを使う

Puppeteer はブラウザ自動化ライブラリです。C#で使えるようにしたものがPuppeteerSharpです。他の言語にも対応したものが作られていて、PHPならPuPHPeteer、PythonならPyppeteerがあります。

ということで今回は動画検索をして上位10件を表示させます。それから以下のNode.jsのスクリプトをエックスサーバーで実行しようとしたのですが、うまくいきませんでした。下記のサイトと同じところでつっかえてしまい、諦めることにしました。

Xサーバーでpuppeteerを動かせなかった

そこで代わりの方法としてHerokuというサービスを使います。

puppeteerの他にrequestとexpressを使います。ではコードを書いていきましょう。

それから取得した動画タイトルとurlを管理するためのクラスをつくります。

おおまかな処理について

最初に実行されるmain関数をつくります。トップページにはとくになにも表示させません。/search/keyword/検索したいキーワード/max/10にアクセスすると検索したいキーワードで検索して上位10件をSearch関数で検索して、その結果をスプレッドシートに書き込みます。もし引数が不正であれば(maxが数字でないとか)、ページに引数が不正である旨表示させます。

それからポート番号ですが、Herokuを使う場合はprocess.env.PORT || 3000でないとうまく動いてくれません。

検索結果を取得するSearch関数

検索結果を取得するSearch関数を示します。

まずヘッドレスブラウザを起動します。そのときのオプションなのですが、puppeteer.launchに渡す引数は、args: [‘–no-sandbox’, ‘–disable-setuid-sandbox’]でなければなりません。Heroku環境かどうかはprocess.env.DYNOが真か偽かで判断できるので三項演算子をつかってLAUNCH_OPTIONにセットしています。

ヘッドレスブラウザを起動したら動画検索をしたときのurlは https://www.youtube.com/results?search_query=検索したいキーワード なので実際にそこにアクセスします。

HTMLを解析して「div.text-wrapper.style-scope.ytd-video-renderer」の要素を抜き出します。ここに動画のタイトルとurlがかかれた要素が存在します。ただし取得したい件数が増えるとスクロールしないと検索結果の一部しか取得できません。全部取得してみて取得したい数よりも少なければスクロールさせて、より多くの結果を取得しようとします。取得した要素数がmaxよりも多ければそれ以上の処理は必要ないので、ループから抜けます。

必要なだけ要素が取得できたら、ここから動画タイトルと動画urlを抜き出します。「div.text-wrapper.style-scope.ytd-video-renderer」のなかの「yt-formatted-string.style-scope.ytd-video-renderer」から動画のタイトルが、「a#video-title.yt-simple-endpoint.style-scope.ytd-video-renderer」から動画のurlが、「yt-formatted-string#text.style-scope.ytd-channel-name.complex-string」からチャンネル名が、「a.yt-simple-endpoint.style-scope.yt-formatted-string」からチャンネルのurlが取得できます。

取得したデータをPageDataクラスのインスタンス内に格納していきます。そしてこのインスタンスはdatasという配列に格納され、Search関数はdatasを返します。

スプレッドシートに送る文字列の生成

次に取得されたデータをスプレッドシートに送ることができるように、文字列に変換します。スクレイピングしたデータをGASを使ってスプレッドシートに書き込むのは簡単と思っていたら意外に難儀した話にあるように二次元配列として送っても処理をしてくれないからです。

取得されたデータを文字列に変換する処理を示します。

改行を利用して文字列を格納する列と行をわけています。改行があれば次の列のデータであり、改行が連続して2つある場合は次の行のデータです。

そのため書き込むデータのなかに改行が存在しないことが前提です。最初に取得したデータから改行を取り除き、これを改行をあいだにいれて連結しています。

最後に連結した文字列をスプレッドシートにPostで送ります。

スプレッドシート側での処理

これをうけとるスプレッドシート側ではスクリプトエディタでGASに以下のように書きます。そしてウェブアプリとしてデプロイし、発行されたurlをNode.jsのSaveToSpreadsheet関数のendPointに設定しなければなりません。

ローカルで動作確認できたらHerokuにpush

あとはこれをHerokuにpushするだけです。コマンドプロンプトでindex.jsがあるフォルダに移動して、

次回以降は、

これで公開することができます。

またスプレッドシートにボタンを配置してボタンをおせば検索結果を表示させるようにするのも面白いかもしれません。

4行H列にキーワード、5行H列に取得したい件数を書いておき、ボタンがおされたらfunc1関数が実行されるようにします。