NodeREDでみんな大好きIGRの時刻表をスクレイピング


岩手県立大学アドベントカレンダーなので岩手っぽいネタにします。

最近NodeRED(enebular)をよく使うので勉強がてらスクレイピングにチャレンジします。

@omega999くんのみんな大好きIGRの時刻表をスクレイピングの記事インスパイアです。

IGR

みんな大好き、いわて銀河鉄道ですね。

今回は滝沢駅の時刻表を抜き出してみます。 http://www.igr.jp/wp/timetable/takizawa

最終的にこんなJSONとして出力してAPI化します。

enebularでスクレイピングチャレンジ

まずはそのままHTMLリソース取得

  • http in
  • http request
  • http response
  • debug

の各ノードをつなげます。

http requestノードのURLに今回のエンドポイントになる滝沢駅の時刻表ページhttp://www.igr.jp/wp/timetable/takizawaを指定します。

デプロイしてURLにアクセスしてデバッグコンソールを確認します。

ちゃんと取れてますね。

これをカスタマイズしてみましょう。

htmlノードを利用

他にいいやり方があるかもしれないですが、 htmlノードを使うとHTMLからCSSセレクタを使用して要素を取り出すことが出来る模様。
便利そう。

ということで使ってみます。

調べたところclass="post"の中のp要素に時刻表が入っている模様です。

こんな感じに設定してあげるとそれっぽい時刻表が取得できました。

  • 抽出する要素: .post p
  • 出力: 要素のテキストのみ, 要素毎の複数のメッセージ

p要素が配列で取得できているイメージです。

Switchノードで絞り込み

県大生がよく使うであろう滝沢駅から盛岡駅方面への電車(上り)を絞り込みます。

Switchノードで盛岡という言葉が含まれている要素を絞り込みます。

  • contains: 盛岡

functionノードでjsonに整形

最後にfunctionノードを挟んでJavaScriptを記述します。最後はhttp outのノードにつないであげればJSON出力されます。

const tmp = msg.payload.match(/(.*) (.*)/g); // 6:16 盛岡の形式を取得

let content = [];
for(let i = 0,len = tmp.length; i<len; i++){
    const item = tmp[i].split(' ');
    content.push({
        time: item[0],
        destination: item[1]
    })
}

msg.payload = {
    title: '滝沢駅上り',
    items: content
}
return msg;

msg.payload.match(/(.*) (.*)/g);の箇所で正規表現でマッチした時刻情報を配列として取ってきて、for文の箇所でjsonに整形しています。

結果

使い勝手がいいかわからないけどJSON出力できました。

まとめ

functionノードを使わずに既存のノードを駆使したいところでしたが、NodeRED力がなさすぎて限界を感じました苦笑

もっとスマートにやれる方法が思いつく人がいたらぜひ教えてください!