今回はNode-REDを使ってWebページの情報を処理してみます。Webページのデータ(HTML)をダウンロード(取得)して処理、保存する方法については以前扱っています。
第6回 Webからデータをダウンロード
https://news.mynavi.jp/techplus/article/natonakucommand-6/
Webページ上のデータを扱うには、なかなか難しい面もあります。多くはスクレイピングしてデータを取り出すことになります。ここらへんUNIXの標準コマンドや言語などでは面倒なこともあります。Webサーバーにデータを返す専用のAPIでも用意されていれば便利なのでしょうが、そのようなことはほとんどないでしょう。このため、Python言語などでHTMLデータから必要な情報を抜き出すスクレイピングが使われてしまうわけです。スクレイピングはHTMLの構造に大きく依存するため、対象となるHTMLの構造が変われば作り直さなければならず手間がかかります。
とは言え現状ではWebページ上のデータはスクレイピングして抜き出すのがいちばん効果的でしょう。
幸にしてNode-REDのベースとなっているNodeJSはWebページで使用されているJavaScript言語が動作します。つまり、大変親和性が高いと言えます。
HTMLデータを取得
それでは基本となるWebページのHTMLを取得してみましょう。取得するWebページは、この連載の第6回です。
まず、新規にフローを作成します。フローのタブの右側にある+ボタンをクリックすると新規にフローが作成されます。
次にinjectノードを配置します。HTMLデータを取得するためには何らかのトリガーが必要なので、ここではinjectノードを使っています。もちろん何らかのトリガーとなるノードであればinjectノードでなくても構いません。
次にネットワークのカテゴリからhttp requestノードをドラッグドロップして配置します。
配置したらhttp requestノードをダブルクリックして設定画面を開きます。
URLの欄に「https://news.mynavi.jp/techplus/article/natonakucommand-6/」と入力します。ここが取得したいWebページのURLになります。今回は他の設定は変更する必要はありません。このまま完了ボタンをクリックします。
次にdebugノードを配置します。今回はデバッグメッセージサイドバーのみに出力するので何も設定する必要はありません。
以下の図のようにノードを繋ぎます。繋いだらデプロイボタンをクリックします。
無事にデプロイが終わったら実行してみましょう。Web上のデータには回線状況によっては時間がかかることがあります。しばらくするとデバッグメッセージサイドバーにHTMLデータが表示されます。エラーでなければHTMLデータ内に「なんとなくコマンド(6)〜といった文字を確認できるはずです。
場合によっては図のようなメッセージが表示されることがあります。
"あなたのフローの認証情報ファイルは、システムによって生成されたキーで暗号化されています。このキーが何らかの理由で失われると、その認証情報ファイルは復号できず、削除して再入力する必要があります。"これは警告ではなくセキュリティに関する注意喚起のメッセージです。Raspberry PiのOS再インストールやNode-REDに関係するディレクトリやファイルなどの破損・消滅などによっても表示されます。
今回のようなサンプルの場合は特段動作には影響がないので、このまま無視して進めても問題ありません。なお、これは独自の暗号化キーをsettings.jsファイルに設定することで解消されます。(設定方法は一番最後に掲載してあります)
特定のHTMLタグ内の文字列を抜き出す
HTMLデータを取得できたのでHTMLタグ内の文字列を抜き出してみましょう。まず、簡単なところでページタイトルを抜き出します。ページのタイトルはtitleタグ内に書かれています。HTMLソースを表示すると以下のハイライト部分がtitleタグ部分になります。このtitleタグで囲まれた文字列を抜き出すわけです。
まず、http requestノードとdebugノードを繋いでいる線を選択して削除します。
次にパーサのカテゴリ内にあるhtmlノードをドラッグドロップして配置します。
配置したら図のように各ノードを繋ぎます。
htmlノードをダブルクリックして設定画面を開きます。抽出する要素にtitleと入力します。titleタグ内の文字を抜き出すので出力の部分では「要素のテキストのみ」を選択します。設定が終わったら完了ボタンをクリックします。
デプロイボタンをクリックします。問題がなければ実行します。すると結果がデバッグメッセージサイドバーに表示されます。配列なので▼をクリックすると内容が展開され表示されます。
ページタイトルを抜き出すはずが、本文内の他の何かのtitleタグの内容まで抜き出されてしまっているようです。今回はページのタイトルだけを抜き出したいのでCSSセレクタを指定する部分を調整する必要があります。titleタグはheadタグ内に1つのはずなので抽出する要素の欄の指定をtitleでなくhead > titleとします。また、出力で「配列化した1つのメッセージ」から「要素毎の複数のメッセージ」に変更します。設定が終わったら完了ボタンを押します。
デプロイしたら実行してみましょう。今度はページのtitleタグの文字だけがデバッグメッセージサイドバーに出力されるはずです。
特定のHTMLタグ内の文字列を抜き出す(functionノード)
先ほどの方法はタグがうまく階層化されているなどの条件を満たさないとうまくいかないことがあります。複雑なCSSセレクタを指定するくらいならfunctionノードでJavaScriptコードを書いた方がわかりやすく便利な場合があります。そこで今度はfunctionノードを使ってtitleタグの文字を抜き出してみます。
まず、htmlノードとdebugノードの線を選択して削除します。
htmlノードをダブルクリックして図のように設定します。設定したら完了ボタンをクリックします。
次にfunctionノードを配置し図のように繋ぎます。
functionノードをダブルクリックして設定画面を開きます。コードの部分に以下のJavaScriptプログラムを入力します。JavaScriptプログラムの最初の1行がpayloadに入っている配列の最初の要素を抜き出してpayloadに書き戻すというものです。[0]を[1]にすると2番目の要素がpayloadに入ります。ページ内に複数の要素があり、必要な箇所だけを抜き出す場合は、この方がやりやすいのではないかと思います。
入力したら完了ボタンをクリックします。
msg.payload = msg.payload[0];
return msg;
入力が終わったらデプロイして実行してみましょう。先ほどと同様にデバッグメッセージサイドバーにはtitleタグ内の文字が表示されます。
ページ内の小見出しを抜き出す
次にページ内の小見出しの文字を抜き出してみましょう。小見出しはh2タグで囲まれており複数あります。先ほどのtitleと同様の方法で処理できます。まず、先ほど作ったフローをコピー&ペーストして再利用してみましょう。必要な部分を囲んで選択します。選択したらマウスの右ボタンをクリックします。メニューが表示されるので「ノードをコピー」の項目を選択します。これでノードがコピーされます。
+ボタンをクリックして新しいフローを追加します。追加したら右ボタンをクリックします。メニューが表示されるので「ノードを貼り付け」を選択します。するとノードが表示されマウスで好きな位置に配置できるようになります。位置を決めたらマウスのボタンをクリックします。
これで準備ができました。htmlノードをダブルクリックして以下の図のように設定します。
次にhtmlノードとfunctionノード、functionノードとdebugノードを繋いでいる線を選択して削除します。削除したら今度は図のように線を繋ぎます。なお、使わないfunctionは、このままにしておいても問題ありません。
デプロイして実行します。するとWebページ内のh2タグの文字だけが抜き出され配列としてデバッグメッセージサイドバーに表示されます。
続きが長くなりそうなので続きは次回。
NOTE:settings.jsファイルの設定
settings.jsファイルを設定する前にNode-REDが動作している場合は停止(コマンドはnode-red-stop)させてください。停止したら以下のようにコマンドを入力します。(viでなくnanoなど他のエディタを使ってもかまいません)
sudo vi ~/.node-red/settings.js
settings.jsファイルの内容が表示されます。 少し下に移動させると「credentialSecret: false,」という行があります。 falseの文字を変更します。これが暗号化のためのパスフレーズ(文字列)になります。ここではmyNaviの文字列にしてありますが、より長く複雑なものにしておくほうが良いかもしれません。ただし、忘れてしまうとトラブル時に復元できなくなってしまうので注意が必要です。 settings.jsファイルは読み出し専用(Readonly)になっているので、viでは「:w!」のようにして強制的に上書き保存します。保存できたら:qとして終了します。なお、Node-REDが動作中の場合はエラーが表示され保存できません。この場合はNode-REDを終了してから保存してください。
著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。