🌐 Node-RED HTML ノードガイド

📚 目次

📖 1. 概要

HTML ノードは、HTMLドキュメントから特定の要素を抽出するノードです。CSSセレクタを使って、Webページから必要なデータを取り出す「Webスクレイピング」に使用します。

🔍 本から特定の章を探すことに例えると:HTML ノードは本の目次を使って特定の章を探すようなものです。「第3章」「著者紹介」など、目的の部分をピンポイントで取り出せます。

HTTP Request HTML Debug

💡 ポイント:

⚙️ 2. 設定詳細

プロパティ

プロパティ説明デフォルト
SelectorCSSセレクタ(抽出対象を指定)(空)
Output出力形式(html/text/属性)html
Property入力HTMLのプロパティmsg.payload
Output to出力先のプロパティmsg.payload
as出力形式(単一/複数メッセージ)single
Prefix属性プレフィックス文字(出力がcomplの場合)_

Output オプション

オプション説明出力例
the html content要素の内部HTML<b>太字</b>テキスト
only the text contentテキストのみ太字テキスト
属性名を指定指定した属性の値href属性なら URL

🎯 3. CSSセレクタの基本

基本セレクタ

セレクタ説明
要素名タグ名で選択p, div, a
.クラス名class属性で選択.article, .title
#IDid属性で選択#header, #main
[属性]属性の有無で選択[href], [data-id]
[属性=値]属性値で選択[type="text"]

組み合わせセレクタ

セレクタ説明
A BAの子孫のBdiv p(div内の全p)
A > BAの直接の子のBul > li(ulの直下のli)
A, BAまたはBh1, h2(h1とh2両方)
A.classAでクラスがclassp.intro

便利なセレクタ

/* n番目の要素 */ li:nth-child(1) /* 1番目のli */ li:nth-child(odd) /* 奇数番目のli */ li:first-child /* 最初のli */ li:last-child /* 最後のli */ /* 属性の部分一致 */ [href^="https"] /* httpsで始まる */ [href$=".pdf"] /* .pdfで終わる */ [href*="example"] /* exampleを含む */

🔧 4. 実用的な使用パターン

📥 サンプルフローのインポート方法:

  1. 下のサンプルフローJSONをコピー
  2. Node-REDエディタで メニュー → 読み込み を選択
  3. JSONをペーストして「読み込み」をクリック

このサンプルフローには、以下で説明するパターンの実例が含まれています。

📥 サンプルフローJSON(クリックで展開)
[ { "id": "html_sample_tab", "type": "tab", "label": "HTML サンプル", "disabled": false, "info": "" }, { "id": "html_comment1", "type": "comment", "z": "html_sample_tab", "name": "━━━ 基本: HTMLからテキスト抽出 ━━━", "info": "", "x": 190, "y": 40, "wires": [] }, { "id": "html_template1", "type": "template", "z": "html_sample_tab", "name": "サンプルHTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "\n\n

メインタイトル

\n
\n

これは紹介文です。

\n

本文の段落1です。

\n

本文の段落2です。

\n
\n \n\n", "output": "str", "x": 160, "y": 100, "wires": [["html_extract_h1", "html_extract_p", "html_extract_links"]] }, { "id": "html_inject1", "type": "inject", "z": "html_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 60, "wires": [["html_template1"]] }, { "id": "html_extract_h1", "type": "html", "z": "html_sample_tab", "name": "h1抽出", "property": "payload", "outproperty": "payload", "tag": "h1", "ret": "text", "as": "single", "chr": "_", "x": 350, "y": 60, "wires": [["html_debug1"]] }, { "id": "html_debug1", "type": "debug", "z": "html_sample_tab", "name": "h1: メインタイトル", "active": true, "tosidebar": true, "console": false, "tostatus": true, "complete": "payload", "targetType": "msg", "statusVal": "payload", "statusType": "auto", "x": 550, "y": 60, "wires": [] }, { "id": "html_extract_p", "type": "html", "z": "html_sample_tab", "name": "全p抽出", "property": "payload", "outproperty": "payload", "tag": "p", "ret": "text", "as": "multi", "chr": "_", "x": 350, "y": 100, "wires": [["html_debug2"]] }, { "id": "html_debug2", "type": "debug", "z": "html_sample_tab", "name": "p: 配列で出力", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 540, "y": 100, "wires": [] }, { "id": "html_extract_links", "type": "html", "z": "html_sample_tab", "name": "リンクURL抽出", "property": "payload", "outproperty": "payload", "tag": "a", "ret": "attr", "as": "multi", "chr": "_", "x": 360, "y": 140, "wires": [["html_debug3"]] }, { "id": "html_debug3", "type": "debug", "z": "html_sample_tab", "name": "href属性", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 540, "y": 140, "wires": [] }, { "id": "html_comment2", "type": "comment", "z": "html_sample_tab", "name": "━━━ クラスやIDで絞り込み ━━━", "info": "", "x": 180, "y": 200, "wires": [] }, { "id": "html_inject2", "type": "inject", "z": "html_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 260, "wires": [["html_template2"]] }, { "id": "html_template2", "type": "template", "z": "html_sample_tab", "name": "クラス付きHTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "
\n
\n

重要ニュース

\n

重要な出来事の概要

\n
\n
\n

通常ニュース1

\n

概要1

\n
\n
\n

通常ニュース2

\n

概要2

\n
\n
", "output": "str", "x": 170, "y": 300, "wires": [["html_extract_class"]] }, { "id": "html_extract_class", "type": "html", "z": "html_sample_tab", "name": ".news-item .title", "property": "payload", "outproperty": "payload", "tag": ".news-item .title", "ret": "text", "as": "multi", "chr": "_", "x": 370, "y": 300, "wires": [["html_debug4"]] }, { "id": "html_debug4", "type": "debug", "z": "html_sample_tab", "name": "ニュースタイトル", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 570, "y": 300, "wires": [] }, { "id": "html_comment3", "type": "comment", "z": "html_sample_tab", "name": "━━━ テーブルデータ抽出 ━━━", "info": "", "x": 180, "y": 360, "wires": [] }, { "id": "html_inject3", "type": "inject", "z": "html_sample_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 420, "wires": [["html_template3"]] }, { "id": "html_template3", "type": "template", "z": "html_sample_tab", "name": "テーブルHTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "\n \n \n \n \n
名前年齢職業
田中30エンジニア
鈴木25デザイナー
佐藤35マネージャー
", "output": "str", "x": 160, "y": 460, "wires": [["html_extract_table"]] }, { "id": "html_extract_table", "type": "html", "z": "html_sample_tab", "name": "td抽出", "property": "payload", "outproperty": "payload", "tag": "table tr td", "ret": "text", "as": "multi", "chr": "_", "x": 350, "y": 460, "wires": [["html_debug5"]] }, { "id": "html_debug5", "type": "debug", "z": "html_sample_tab", "name": "テーブルデータ", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 540, "y": 460, "wires": [] } ]

使用パターン

パターン1: 基本テキスト抽出(h1、p、リンク)

サンプルフローの「基本: HTMLからテキスト抽出」を参照してください。

サンプルHTML h1抽出 メインタイトル

ポイント:

パターン2: クラスやIDで絞り込み

サンプルフローの「クラスやIDで絞り込み」を参照してください。

クラス付きHTML .news-item .title ニュースタイトル

ポイント:

パターン3: テーブルデータ抽出

サンプルフローの「テーブルデータ抽出」を参照してください。

テーブルHTML table tr td テーブルデータ

ポイント:

📝 5. 演習問題

演習1: 見出し抽出 初級

📋 課題: HTMLから全ての h2 タグのテキストを抽出してください。

✅ 成功の条件:

💡 ヒント

Selector に h2、Output に text を設定します。

✅ 解答例フロー
[ {"id": "ex1_tab", "type": "tab", "label": "演習1"}, {"id": "ex1_inject", "type": "inject", "z": "ex1_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 80, "wires": [["ex1_template"]]}, {"id": "ex1_template", "type": "template", "z": "ex1_tab", "name": "HTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "

タイトル

\n

セクション1

\n

本文1

\n

セクション2

\n

本文2

\n

セクション3

\n

本文3

", "output": "str", "x": 270, "y": 80, "wires": [["ex1_html"]]}, {"id": "ex1_html", "type": "html", "z": "ex1_tab", "name": "h2抽出", "property": "payload", "outproperty": "payload", "tag": "h2", "ret": "text", "as": "multi", "chr": "_", "x": 410, "y": 80, "wires": [["ex1_debug"]]}, {"id": "ex1_debug", "type": "debug", "z": "ex1_tab", "name": "結果", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 550, "y": 80, "wires": []} ]

演習2: リンクURL抽出 初級

📋 課題: HTML内の全ての a タグから href 属性を抽出してください。

✅ 成功の条件:

💡 ヒント

Output を「属性名を指定」にして href と入力します。

✅ 解答例フロー
[ {"id": "ex2_tab", "type": "tab", "label": "演習2"}, {"id": "ex2_inject", "type": "inject", "z": "ex2_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 80, "wires": [["ex2_template"]]}, {"id": "ex2_template", "type": "template", "z": "ex2_tab", "name": "リンクHTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "", "output": "str", "x": 280, "y": 80, "wires": [["ex2_html"]]}, {"id": "ex2_html", "type": "html", "z": "ex2_tab", "name": "href抽出", "property": "payload", "outproperty": "payload", "tag": "a", "ret": "attr", "as": "multi", "chr": "_", "x": 430, "y": 80, "wires": [["ex2_debug"]]}, {"id": "ex2_debug", "type": "debug", "z": "ex2_tab", "name": "URL一覧", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 570, "y": 80, "wires": []} ]

演習3: クラスで絞り込み 中級

📋 課題: class="highlight" を持つ要素のテキストのみを抽出してください。

✅ 成功の条件:

💡 ヒント

Selector に .highlight を指定します。

✅ 解答例フロー
[ {"id": "ex3_tab", "type": "tab", "label": "演習3"}, {"id": "ex3_inject", "type": "inject", "z": "ex3_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 80, "wires": [["ex3_template"]]}, {"id": "ex3_template", "type": "template", "z": "ex3_tab", "name": "HTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "
    \n
  • 通常項目1
  • \n
  • 重要項目1
  • \n
  • 通常項目2
  • \n
  • 重要項目2
  • \n
  • 通常項目3
  • \n
", "output": "str", "x": 270, "y": 80, "wires": [["ex3_html"]]}, {"id": "ex3_html", "type": "html", "z": "ex3_tab", "name": ".highlight", "property": "payload", "outproperty": "payload", "tag": ".highlight", "ret": "text", "as": "multi", "chr": "_", "x": 420, "y": 80, "wires": [["ex3_debug"]]}, {"id": "ex3_debug", "type": "debug", "z": "ex3_tab", "name": "重要項目のみ", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 580, "y": 80, "wires": []} ]

演習4: 複合セレクタ 上級

📋 課題: id="main" の div 内にある、class="item" を持つ要素のテキストを抽出してください。

✅ 成功の条件:

💡 ヒント

複合セレクタ: #main .item

✅ 解答例フロー
[ {"id": "ex4_tab", "type": "tab", "label": "演習4"}, {"id": "ex4_inject", "type": "inject", "z": "ex4_tab", "name": "実行", "props": [], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "x": 130, "y": 80, "wires": [["ex4_template"]]}, {"id": "ex4_template", "type": "template", "z": "ex4_tab", "name": "HTML", "field": "payload", "fieldType": "msg", "format": "html", "syntax": "plain", "template": "
\n サイドバー項目\n
\n
\n メイン項目1\n メイン項目2\n その他\n
", "output": "str", "x": 270, "y": 80, "wires": [["ex4_html"]]}, {"id": "ex4_html", "type": "html", "z": "ex4_tab", "name": "#main .item", "property": "payload", "outproperty": "payload", "tag": "#main .item", "ret": "text", "as": "multi", "chr": "_", "x": 420, "y": 80, "wires": [["ex4_debug"]]}, {"id": "ex4_debug", "type": "debug", "z": "ex4_tab", "name": "メイン内のみ", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "x": 580, "y": 80, "wires": []} ]

✅ 6. まとめ

🎯 重要ポイント:

⚠️ 注意事項:

🏭 7. 実務活用例

ケース1: ニュースサイトからの情報収集

ニュースサイトから記事タイトルとリンクを定期的に取得してデータベースに保存。

ケース2: 価格監視

ECサイトから商品価格を抽出し、価格変動を監視・通知。

ケース3: データ変換

HTMLレポートから表データを抽出してJSON形式に変換。

ケース4: コンテンツ集約

複数サイトから特定のコンテンツを抽出してダッシュボードに表示。

📚 Node-RED 公式ドキュメント

🏠