n8nによる「本格的ワークフロー」のハンズオン第4回です。
今回はLoop処理に入って行きましょう。
前回までで「各記事の基本的なメタ情報」を取得できるところまで来ました。
今回からは、その情報をもとに、記事データ配列でLoopを回して、その中で本文を取得・要約してデータ整形などを記事単位で実施するやり方を見ていきます。
ここまでで作成したワークフローは下図のようになっているはずです。

また、ワークフローの現時点の出力、つまり、これから作成するノードの入力は下記のようなものです。
[
{ // 最新記事のメタ情報(タイトル・URL・公開日・公開日DateObject)
"articleTitle": "Gmailの新しいガイドライン:新しいメール要件を満たすには?",
"articleURL": "https://blog.future.ad.jp/gmailの新しいガイドライン新しいメール要件を満たすには",
"articleDate": "2024-06-11",
"objDate": 2025-10-27T00:00:00.000Z
},
{ // 最新から2番めの記事のメタ情報
・・・・
},
・・・・
{ // 最新からn番めの記事のメタ情報
・・・・
}
]
ブログのサムネイルページからスクレイピングで取得した記事の情報が整理され、最新記事からn件(今回は7件)分のデータが配列で保持されています。配列の中身は連想配列でタイトル・本文URL・公開日・公開日DateObjectです。
全貌における現在地点
今回、目指しているワークフロー全貌における現在地点は、下記の通りで、「全体・一覧としての処理」までが出来た所です。

ここから後半戦です。フローチャートの下半分のループ処理に今回から入っていきます。
なぜLoopノードを使用するか?
これまでの解説の通り、n8nでは各ノードは「暗黙的なLoop処理」を自動的に実施してくれます。
複数のアイテムを入力値として渡して、適切な設定を行えば、自動的に必要な処理をアイテム数の回数分Loopして処理をし、後続ノードに配列で引き渡しをしてくれます。
では、なぜ明示的なLoop処理・Loopノードが必要なのでしょうか?
それは、各ノードの「暗黙的Loop処理」は、それぞれのノードで独立した処理が行われてしまい、各ノードで扱われている配列は、本質的には「別々のもの」であり関連性が薄いためです。各処理で得られた結果を結合する場合は、「配列の並び順」と「実行順序」のみが同一性・関連性の根拠となるため、やや関係性が曖昧な処理となります。
このため、それぞれの「対象」ごとに、強い関連性が欲しい場合は、Loop内で閉じた連続処理が望ましいケースがあります。このようなケースでは、Loopノードを設置して、そのLoopの中で複数のアクションノードを設置して連続処理をさせると良いでしょう。
今回のサンプルケースでは、まだまだモデルが単純であるため、暗黙的Loopのつなぎ合わせでも何とか処理ができそうですが、Loopノードを理解するためにも、今回はLoopノードを設置して取り扱ってみます。
6. Loopノード:明示的Loop処理
各記事ごとに、以下の処理を「Loop内で閉じて」連続的に実施し、「同一レコード内のデータ処理」という明確な意味づけをするため、Loopノードを設置していきます。
- 記事本文ページにアクセス:HTTP Requestノード
- 記事ページをparse。本文・執筆者などの情報を取得する。:HTMLノード
- 本文を要約する:Basic LLM Chain + Gemini Chat Model
- 結果を集約し、出力分の「1レコード」として整形

例によって、既存ワークフローの右側『+』に、新しくLoop Over Itemsノードを接続していきましょう。(本記事では簡略化してLoopノードと呼称しています。)
Loopノードの設定が開きます。
今回は特に明示的に設定を変更する必要はありません。そのままBack to canvasをクリックしてキャンバスに戻りましょう。

設置後、下記のような状態になります。
※ ノードが増えてきたので、マウスでDragしてキャンバス上の見た目を整えています。

Loopノードには「出口」が2つ用意されています。
done と loop です。
この内 done は「全てのLoop処理が完了した後」に出力が行われて、更に後続のアクションノードに接続させていく場所になります。
loopの方が、「Loopの中で行わせたい処理」となります。
Replace Meのところを好きなアクションノードに変更して使用することができます。また、Loopの中に複数のアクションノードを設置することも可能です。

7. Loop内のHTTP Reqestノード:記事URLへのアクセス
さっそく、Loop内部にアクションノードを設置していってみましょう。

既におなじみのHTTP Requestノードです。
こちらの設定は下記のように行います。設定の方法は、第2回で解説した内容と同様です。
- Method:GET
- URL:{{ $json.articleURL }}
- Header Parameters - Name:User-Agent
- Header Parameters - Value:Mozilla/5.0 (compatible; n8n-scraper; +https://example.com/)
※ Headerはマナーとして指定。n8nからのスキャン目的と判別出来るように)
URLは、前段階のワークフローで取得済みのメタ情報から取得します。
コードノードで解説した特殊変数 $json がここでも使用できます。
Loop内のアクションノードにおいて、Loopノードから引き渡される $input は、コードノードにおける 「Run Once for each Item」Modeでの挙動と同様です。つまり、Loopに渡させれている items の全要素から、Loopごとに順に item が取り出されて、$input に 引き渡されています。
よって、「取り扱いたい値」へアプローチするには、下記のいずれかとなります。
- $itemData = $input.item.json
- $itemData = $json

ここまでの設定で、試運転してみて、以下のように、右辺に「記事本体のHTML」が取得できていればOKです。

8. Loop内のHTMLノード:記事本体の内容解析
続いてHTMLノードも設置していきます。
直前のHTTP Requestノードで取得した記事本体のHTMLを解析して、本文や執筆者などの欲しい情報をスクレイピングで取得していきます。

HTMLノードをLoop内のHTTP Requestノードに続けて設置し、例によってExtract HTML Content を選択します。
続くHTMLノードの設定では下記のように設定しましょう。
- Source Data:JSON
- JSON Property:articles
Extraction Values 3つ分(本文・カテゴリ・執筆者)
まず、1つ目:本文
- Key:ArticleContent
- CSS Selector:#hs_cos_wrapper_post_body
- Return Value:Text
- Return Array:OFF
まず、2つ目:カテゴリ(複数あり)
- Key:ArticleCategory
- CSS Selector:div.article-mv-category a.el-tag.size-sm2
- Return Value:Text
- Return Array:ON
まず、1つ目:本文
- Key:ArticleAuther
- CSS Selector:div.article-mv-auther a
- Return Value:TEXT
- Return Array:OFF
このように設定して、試運転(Execute step)してみましょう。

このように、右辺に本文・カテゴリ・執筆者が出力されていればOKです。

9. Loopの結果を確認する:done側にアクションノードを接続
Loopがきちんと処理できているか、done側に適当なノードを接続して確認してみましょう。
何かを接続して、設定ダイアログを見るだけでも左辺にInputとして入力値(つまりLoopの出力値)が確認できるので、接続するノードは何でも良いのですが、復習を兼ねてcodeノードを置いてみます。
Loopノードに後続処理を設置するには、Doneの先に伸びている『+』をクリックして、アクションノードを選択します。今回は、Codeノードを選択しましょう。
コードは適当でOKですが、せっかくなので、少しデータを整形するようにしてみます。
const customOutput = [];
for (const item of $input.all()) {
const cuOut = {};
const cuIn = item.json;
cuOut["ArticleContentHead"] = cuIn["ArticleContent"].substr(0,100);
cuOut["ArticleCategory"] = cuIn["ArticleCategory"];
cuOut["ArticleAuther"] = cuIn["ArticleAuther"];
customOutput.push(cuOut);
}
return customOutput;
本文が長いので100文字でカット。他の値はそのまま。
こちらで試運転(Execute step) をしてみて、下記のように出力されていればOKです。

Loopの中で、記事ごとに『本文・カテゴリ・執筆者』の情報が取得されて、それが配列に格納されていて、Loopから接続されたCodeノードで、本文が100文字にカットされてから、出力されていることが見て取れます。
キャンバス画面でも、Logsで各ノードの処理結果を眺めることが出来ます。
最終のCodeノードの出力結果が下記のように確認できていればOKです。

ここまでのワークフローで下記のことが出来るようになりました。記事ごとに、本文・カテゴリ
- ブログのサムネイルページにアクセス
- 記事一覧を一括取得して、タイトル・記事URL・公開日等のメタ情報を配列で保持
- ループ処理で、各記事にアクセスして、本文・カテゴリ・執筆者を取得
- 確認ように簡単に整形し、ループ処理の正常動作を確認
今回はここまでにしましょう。
次回はLoop内でデータをレコード的に扱って、Loop内でデータをそれぞれに集約・整形を行う方法に触れていきたいと思います。
- トリガーの設置【Done】
- 特定のURLから内容を取得する ▶ HTTP Request ノード【Done】
- HTMLから要素を部会・取得する ▶ HTMLノード【Done】
- 配列データの扱い方と暗黙的ループ処理【Done】
- コードによる自由な処理 ▶ Codeノード【Done】
- 明示的なループ処理 ▶ Loopノード【Done:今回解説】
- フィールド生成・制御 ▶ MakeFieldsノード → NEXT
- AIノードへの情報連携 ▶ Basic LLM Chain
- 処理済みの任意ノードの値の活用する【Done】
- Googleスプレッドシートへのレコード出力 ▶ Google Sheetノード
- Google Sheet API への アクセス許可の手順 ▶ Google Sheets account 設定

