特定のWebサイトを定期的にチェックして特定のキーワードが含まれていたら
通知してくれる仕組みを1つ覚えておくと色々重宝する。
例えば
会社に社員用Webサイトがあるなら、
(そしてそのサイトがRSSもメール通知も提供してないなら)
そこに「重要」とか「人事」とかのキーワードを含む記事が投稿された時に
通知を受け取れるようにしておけば、
いちいちサイトをチェックしにいかなくても
逃さず確認できる。
また、Webスクレイピングする方法を覚えておけば、
通知を受け取る以外にも、
画面キャプチャの撮影や画像やテキストの収集を
自動化したり、作成したWebシステムの画面テストを行う、
等の応用もしやすくなる。
今回は Node.js + Grunt + cheerio-httpcli を使用して
手軽にWebサイトのデータをチェックする方法を紹介する。
今週の「世界の果てまでイッテQ!」で「QTube」を放送するかをチェックする
実はうちの長女がロッチ中岡のQTubeのコーナーを気に入っていて、
「今週は中岡は出ないのか?」と大層楽しみにしている。
しかし、残念ながら不定期で放送されるので見逃すことが多い。
パパのプログラムスキルが家族の役に立てるチャンス!ということで
毎週日本テレビの番組表をチェックして
「QTube」を放送するかどうかをチャットワークに通知する
スクリプトを作ってみた。
日本テレビの今週の番組表は下記のページで確認できる。
各番組の詳細は下記のような詳細ページにリンクされているようだ。
http://www.ntv.co.jp/program/detail/21849765.html
明日(5/1)は「QTube」を放送するらしい。
HTMLのソースを確認したところ、
番組表のページで「世界の果てまでイッテQ」が
含まれるリンクから詳細ページを開き、
そこの「番組内容」の中に「中岡QTube」が含まれていたら
放送されるとみて良さそうだ。
チェックスクリプトを書く
「qtube_notifier」というプロジェクト名をつけた。
package.json
{ "name": "qtube_notifier", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { "cheerio-httpcli": "^0.6.8", "grunt": "^0.4.5", "grunt-exec": "^0.4.6", "grunt-http": "^2.0.1" } }
Gruntfile.js
module.exports = function(grunt) { grunt.initConfig({ http: { notify: { options: { url: "https://api.chatwork.com/v1/rooms/<チャットワークルームID>/messages", method: "POST", headers: { "X-ChatWorkToken": "<チャットワークAPIキー>" }, form: { body: "QTube情報はありません" } } } }, exec: { check_qtube_schedule: { cmd: "node index.js", callback: function (err, stdout, strerr) { if (stdout) { if (stdout.trim() != "") { grunt.config("http.notify.options.form.body", "QTube情報です:\n" + stdout); } } if (err) { grunt.config("http.notify.options.form.body", "QTubeチェックスクリプトでエラーです:\n" + err); } } } } }); grunt.loadNpmTasks("grunt-exec"); grunt.loadNpmTasks("grunt-http"); grunt.registerTask("default", ["exec:check_qtube_schedule", "http:notify"]); };
index.js
var cheerioCli = require('cheerio-httpcli'); cheerioCli.fetch("http://www.ntv.co.jp/program/", {}) .then(function (result) { var linkList = result.$("h3:contains('世界の果てまでイッテQ')"); var detailLink = linkList[0].parent.attribs.href; //console.log(detailLink); return cheerioCli.fetch("http://www.ntv.co.jp/program/" + detailLink, {}); }) .then(function (result) { var oaDateTime = result.$("h3.oaDate").text(); console.log(oaDateTime); var programText = result.$("div#programArea .program p").text(); if (/中岡QTube/.test(programText)) { console.log("QTubeあります!"); console.log(result.$.documentInfo().url); } else { console.log("QTubeありません。"); } }) .catch(function (err) { console.log(err); }) .finally(function () { //console.log("done"); });
Node.jsとGrunt-cliがインストールされた環境で、
上記3ファイルをqtube_notifierというフォルダに入れて
チャットワーク情報を編集し、
npm install
を実行後
grunt
を実行すると今週「QTube」を放送するかどうかが
チャットワークに通知される。
あとは毎週実行されるように
タスクスケジューラなりcrondなりに
スケジュールを登録しておく。
詳細ページの内容は更新されるようなので、
放送曜日(日曜)前の金曜日くらいに
このスクリプトが流れるようにするのが良さそうだ。
内容説明
今回のスクリプトの構成は、
「Webサイトにアクセスして内容をチェックする」部分と
「チャットワークに通知する」部分に分けている。
チャットワークに通知する部分については、
過去の記事と同様にGruntのgrunt-httpパッケージを
使っている。
Gruntfile.js
http: { notify: { options: { url: "https://api.chatwork.com/v1/rooms/<チャットワークルームID>/messages", method: "POST", headers: { "X-ChatWorkToken": "<チャットワークAPIキー>" }, form: { body: "QTube情報はありません" } } } }, ... grunt.loadNpmTasks("grunt-http");
これだけの記述で使いまわせるのは楽で良い。
Webサイトにアクセスして内容をチェックする部分については、
Gruntからindex.jsというNode.jsスクリプトを呼び出している。
ここでは「grunt-exec」という外部コマンドを呼び出せるパッケージを
使用している。
以前は「grunt-run」というパッケージを使っていたのだが、
「grunt-exec」はコマンドの出力をGrunt側で受け取れるので、
チェック結果をチャットワークに流すためにこちらを使用した。
exec: { check_qtube_schedule: { cmd: "node index.js", callback: function (err, stdout, strerr) { if (stdout) { if (stdout.trim() != "") { grunt.config("http.notify.options.form.body", "QTube情報です:\n" + stdout); } } if (err) { grunt.config("http.notify.options.form.body", "QTubeチェックスクリプトでエラーです:\n" + err); } } } } }); grunt.loadNpmTasks("grunt-exec");
コマンドとして「node index.js」を実行するように指定し、
出力内容を「http.notify.options.form.body」、
つまりチャットワークのメッセージ内容に設定している。
grunt-execで何かしらのスクリプトを実行し、
grunt-configで実行結果をチャットワークメッセージに設定し、
grunt-httpでチャットワークにその内容を通知する、
という組み合わせは今後も色々応用できそうだ。
index.js内では、実際に番組表のページにアクセスして
内容をチェックしている。
Webスクレイピング用のライブラリやツールは
Javascriptで使えるものでも色々あるようだが、
今回はcheerio-httpcliを使ってみた。
取得したページの内容にjQuery風にアクセスできるのが良い。
処理内容としては:
- fetchで番組表ページの内容を取得する
- 取得内容から「世界の果てまでイッテQ」を含むh3タグを取り出す
- 見つかったh3タグの親aタグのリンク先(詳細ページ)を取得する
- 詳細ページの内容を取得する
- 「oaDate」というclass名を持つh3タグから放送日時を取得し、出力する
- 「programArea」というid名を持つdivタグのテキストを取得する
- テキストに「中岡QTube」が含まれるかチェックする
- 含まれていたら「QTubeあります!」というメッセージと詳細ページURLを出力する
- 含まれていなければ「QTubeありません」と出力する
という内容になっている。
おわり
今回のスクリプトを応用するには、
cheerio-httpcliの機能を学んでindex.jsの内容を書き換える必要があるが、
フロントエンドでjQueryに触れたことのある方ならば
それほどとっつきにくいものではないと思う。
今回はスクレイピングというほどの内容ではなかったが、
またいずれ一括取得系スクリプトも作成してみたい。
JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック
- 作者: クジラ飛行机
- 出版社/メーカー: ソシム
- 発売日: 2015/08/31
- メディア: 単行本
- この商品を含むブログ (2件) を見る