puppeteerを使ってyoutubeの新着動画を探そう


動機

良い紳士向けMMDが出ているかもしれない。
チェックしなくてはならない。

成果物

youtube_puppet(github)
※slackに関する処理にtoken情報が記載されていたため、そのjsファイルだけはpushしていない状態です。
上記をbat経由で呼び出しています。
トリガーとしてタスクスケジューラーを使用しています。
(将来的にはタスクスケジューラーは止めて別のにする予定です。)

最終的な成果物の出力イメージは以下画像

概要

簡単に成果物の概要を説明をします。
まず、実現したいこととしては「本日に投稿された紳士向けMMD動画を取得し、それをslack上に特定の時間に流したい」ということです。

・紳士向けMMD動画を取得する方法を考えます。
これはいわゆるスクレイピング技術で解決できるでしょう。
クローラーとも呼ばれます。
以下参考
ウェブスクレイピング(wiki)

紳士向けMMD動画を取得することに関しては上記で完了しました。

・slackに投稿する方法を考えます
slackに投稿することに関しては以下を参考にすると良いでしょう。
postMessage
slackAPIを使いたいが、どこでtokenを発行するのか分からない人は下記リンクを参照してください。
https://api.slack.com/apps

・特定の時間に起動させる方法を考えます
手段は色々ありますが、
最も簡単な方法だと簡易なbatを書き、それをタスクスケジューラーで呼び出すことだと思います。
以下参考
Windowsでbatファイルを自動実行したい時(タスクスケジューラの設定)

別にサーバーを立てたりクラウドでやっても構わないと思います。

以下もうちょっと詳しく解説。

URLの取得

上記画像のように何を検索するか、対象期間はいつにするかを設定し、その際のURLを使えば望みの物が拾えると思います。
今回は「紳士向け MMD」と検索し、フィルターを使い「今日」に絞りました。

puppeteerの出番です。

puppeteerを使い、スレイピングしていきましょう。
そのためにまずF12を押してhtmlを見ていきましょう。
※各自で確認お願いします。

結果だけ言うと欲しいものとしては
document.getElementsByClassName('text-wrapper')
こんな感じで一覧が取れそうでした。
そこからさらに必要な情報を抜き取っていけば望みのものが出来そうです。
具体的にはtext-wrapper配下にある
#meta > #title-wrapper > .title-and-badge > a
のhrefがあれば十分です。
なのでpuppeteerを使ってそれを取得しましょう。

puppeteerの使い方は下記が参考になると思います。
puppeteerでの要素の取得方法

puppeteerの基礎から知りたい方は書籍を買うといいでしょう。
私は下記の書籍のみ購入し、後はネットで調べました。
Puppeteer入門 スクレイピング+Web操作自動処理プログラミング Kindle版

一度書店で立ち読みしてから購入を検討されると良いと思います。

slackAPIを使って投稿

実際のソースを貼るとtokenとか丸見えだったんです。
tokenだけ別ファイルにするとかしてpushしようと思ったんですがめんどくさくなったので
コードを貼り付けます。

const request_promise = require("request-promise");
const SLACK_TOKEN = 'とーくん';
const CHANNEL_ID = 'ちゃんねるID';
const USER_NAME = 'ぼっとのなまえ';

exports.send_message = items => {
  const messages = items.map(item => {
    return item.href;
  });

  messages.forEach(message => {
    (async () => {
      console.log(
        await request_promise({
          uri : 'https://slack.com/api/chat.postMessage',
          method : "POST",
          headers : {
              'content-type' : 'application/x-www-form-urlencoded',
              'charset' : 'utf-8'
          },
          form : {
            token: SLACK_TOKEN,
            channel: CHANNEL_ID ,
            username: USER_NAME ,
            text: message
          },
          json : true
        })
      )
    })()
  });
}

slackのメッセージ投稿については下記が参考になると思います。
NodejsでSlackにメッセージ投稿(2019年1月版)

最終的な成果

一番上の参考画像の通り、slackにURLが投稿されて、動画の一覧が出てきました。

あとがき

結構簡単に作れたのでpuppeteer面白いなぁという感想です。
コードは結構拾ってきた部分が多いので記述的にこれで良いのか不安な部分があったりします。
変な部分があれば良かったら指摘してください。

今回は学習目的のためpuppeteerを使いましたが、本来であればAPIをたたいたほうが賢いです。
youtube data APIを調べるといいと思います。

以上です。
最後まで読んでいただいた方ありがとうございました。