n8nで自動ブログ生成システムを構築【Apify×ChatGPT活用ガイド】

毎日のニュース記事をクロールしてブログ記事を自動生成したい…そんな悩みはありませんか?本記事では、n8nとApifyを組み合わせて、1日1回の定期実行でニュースサイトから自動的にコンテンツを収集し、重複なくAIでブログ記事に変換する完全自動化ワークフローを段階的に解説します。コード知識がない初心者でも、ノーコード環境で実装できる実践的な手法です。


目次

  1. なぜn8n×Apifyの組み合わせが必要か
  2. Website Content Crawlerの基本概要
  3. 第1段階:ワークフロー全体の設計
  4. 第2段階:Website Content Crawlerの最適設定
  5. 第3段階:n8n内でのクローリング実装
  6. 第4段階:重複排除の仕組み
  7. 第5段階:AIによる記事生成
  8. 実装上の注意点とトラブルシューティング
  9. まとめ

なぜn8n×Apifyの組み合わせが必要か

ニュースサイトやブログから定期的にコンテンツを自動収集する場合、単純なWeb APIではできない課題が生じます。

n8nの役割:複数の外部サービスを連携させて、スケジュール実行と条件分岐を実現するワークフロー基盤

Apifyの役割:JavaScriptが実行される動的ページから正確にテキストコンテンツを抽出し、LLM(ChatGPT等)の入力に適したフォーマット(Markdown)で返す

この2つを組み合わせることで、完全な自動化が実現します。


Website Content Crawlerの基本概要

Website Content Crawlerとは、Apifyが提供する「Webサイト全体を自動で巡回してテキストコンテンツを抽出するツール」です。LLM(ChatGPT、Claude等の大規模言語モデル)向けに特別に設計されており、広告やナビゲーションなどのノイズを自動削除し、重要なコンテンツのみを抽出します。

主な特徴

  • 複数のクローラータイプから選択可能(自動最適化、ブラウザレンダリング、HTTP直接アクセス)
  • 出力形式をプレーンテキスト、Markdown、HTMLから選択可能
  • ページメタデータ(タイトル、著者、公開日)も自動抽出
  • 日本語サイトの対応も良好

第1段階:ワークフロー全体の設計

n8nで実装するワークフローは以下の10段階から構成されます。

必要なコンポーネント一覧

コンポーネント役割
Schedule(Cron)毎日決まった時刻(例:午前9時)にワークフロー開始
Apify ノードWebsite Content Crawlerを実行してページをクロール
SQLite/PostgreSQL過去にクロール済みのURLを記録するデータベース
Crypto ノードURLのMD5ハッシュ生成(重複判定用)
If ノード重複判定の条件分岐
Loop Over Items複数のページを順番に処理
Wait ノードレート制限対策の待機
OpenAI ノードAIでブログ記事を自動生成
HTTP RequestWordPress等に記事を自動公開
Error Handlerエラー時の通知処理

事前準備:APIキーの取得

実装前に3つのAPIキーを用意します。

1. Apify API キー
Apifyのアカウント作成後、Settings → API & Integrations から取得

2. OpenAI API キー
OpenAI Platform(platform.openai.com)のAPI keysセクションから生成

3. WordPress REST API認証情報(オプション)
自社ブログに自動公開する場合のみ必要

これらをn8nのCredential Manager(画面左下の鍵マーク)で登録しておくと、ノード設定時に選択するだけで使用可能になります。


第2段階:Website Content Crawlerの最適設定

クローラータイプの選択ガイド

Website Content Crawlerは3種類のクローラーから選択できます。1日周期のニュース収集を想定した場合の選択基準は以下の通り。

クローラータイプ速度コスト用途推奨度
Raw HTTP高速最安(1000ページ/0.2ドル)静的サイト(テキスト記事中心)★★☆
Adaptive中速中程度(1000ページ/1-3ドル)混合型(推奨)★★★
Headless Browser低速最高(1000ページ/5-10ドル)動的ページ(JavaScript必須)★★☆

ニュース・ブログサイトの場合、Adaptiveが最適です。Adaptiveは静的ページではHTTPリクエストで高速処理し、JavaScriptが必要なページでは自動的にブラウザに切り替えるため、パフォーマンスとコストのバランスが最良です。

設定例:複数ニュースサイトのクロール

{
  "startUrls": [
    {"url": "https://techcrunch.com"},
    {"url": "https://www.theverge.com"},
    {"url": "https://news.ycombinator.com"}
  ],
  "maxCrawlPages": 50,
  "crawlerType": "adaptive",
  "outputFormat": "markdown",
  "removeHtmlElements": "nav, header, footer, .modal, .advertisement, script",
  "removeCookieWarnings": true
}

各パラメータの説明

  • startUrls:クロール開始URL(複数指定可能)
  • maxCrawlPages:1回のクロールで取得する上限ページ数
  • crawlerType:自動最適化を選択
  • outputFormat:LLM入力用にMarkdownを指定
  • removeHtmlElements:ナビゲーション、フッター、広告などを自動削除
  • removeCookieWarnings:クッキー同意バナーを自動非表示

動的コンテンツ対応(無限スクロール対応)

ニュースサイトの中には無限スクロールで記事を読み込むサイトもあります。その場合は以下を追加:

{
  "waitForDynamicContent": 5,
  "maxScrollHeight": 3000,
  "expandClickableElements": false
}

これにより、ページ読み込み後5秒待機し、その間にJavaScriptで動的に生成されたコンテンツも取得します。


第3段階:n8n内でのクローリング実装

ステップ1:Daily Cronトリガーの設定

n8n Canvasを開き、「Add Node」から「Schedule」を選択します。

設定項目:

  • Trigger Interval:Daily
  • Time:09:00(毎日午前9時)

Cron式では 0 9 * * * と指定することも可能です。

ステップ2:Apifyノードの追加

Schedule ノードの下にApifyノードを追加します。

操作選択:「Run an Actor synchronously and get dataset items」を選択

入力パラメータ設定

項目入力値
Actor IDapify/website-content-crawler
startUrls[{"url": "https://example.com"}]
maxCrawlPages50
crawlerTypeadaptive
outputFormatmarkdown

ノード実行後、以下の形式でデータが返されます:

{
  "url": "https://example.com/article-123",
  "markdown": "# 記事タイトル\n\n本文内容...",
  "text": "記事タイトル\n本文内容...",
  "metadata": {
    "title": "記事タイトル",
    "author": "著者名",
    "publishedDate": "2025-01-15"
  }
}

ステップ3:SQLiteデータベースの初期設定

別途のSQLiteノードで、クローリング履歴テーブルを作成します。

SQL実行例

CREATE TABLE IF NOT EXISTS crawled_urls (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  url TEXT UNIQUE NOT NULL,
  url_hash TEXT NOT NULL,
  title TEXT,
  content_hash TEXT,
  crawled_date DATETIME DEFAULT CURRENT_TIMESTAMP,
  status TEXT DEFAULT 'new'
);

CREATE INDEX idx_url_hash ON crawled_urls(url_hash);
CREATE INDEX idx_content_hash ON crawled_urls(content_hash);

この実行は初回のみ。以降は重複判定に使用されます。


第4段階:重複排除の仕組み

MD5ハッシュ生成による重複判定

重複を排除するために、URL のMD5ハッシュ値を生成して比較します。

ステップ1:Cryptoノードでハッシュ生成

Apifyノード後にCryptoノードを追加:

設定:

  • Type:MD5
  • Value:{{ $json.url }}
  • Property Name:url_hash

出力例:

{
  "url": "https://example.com/article-1",
  "url_hash": "abc123def456ghi789..."
}

ステップ2:SQL クエリで重複判定

SQL ノードを追加して、既にクロール済みのURLかを判定:

SELECT COUNT(*) as duplicate_count 
FROM crawled_urls 
WHERE url_hash = '{{ $json.url_hash }}'

結果が0なら新規、1以上なら重複です。

ステップ3:If ノードで条件分岐

Ifノードを追加して、重複判定の結果に基づいて処理を分岐:

If duplicate_count > 0:
  → End workflow (スキップ)
Else:
  → Continue to next step (新規コンテンツとして処理)

コンテンツハッシュによる高度な重複排除

URLは異なっても、記事コンテンツが全く同じ(転載、配信記事等)場合も排除したい場合:

SELECT COUNT(*) as dup_content
FROM crawled_urls
WHERE content_hash = md5('{{ $json.markdown }}')
AND crawled_date > DATETIME('now', '-30 days')

このようにコンテンツ自体のハッシュ値を比較することで、異なるURL、同一内容の記事を排除できます。


第5段階:AIによる記事生成

OpenAIノードの設定

重複判定を通過した新規コンテンツを、OpenAI ノードでブログ記事に変換します。

Model:gpt-4 または gpt-4-turbo(品質重視の場合)

Temperature:0.7(創造性と一貫性のバランス)

Prompt(プロンプト):以下を参考にカスタマイズ

以下のニュース記事「{{ $json.metadata.title }}」を日本語でわかりやすいブログ記事に執筆してください。

元の記事:
{{ $json.markdown }}

要件:
- 1000~1500字程度
- 読みやすい日本語で、複雑な専門用語は説明を付ける
- H2見出しを2~3個含める
- 導入:なぜこのニュースが重要か
- 本論:詳細な解説
- 結論:読者への示唆・応用例
- 最後に「参考記事」セクションを追加(元のURL記載)

出力フォーマット:Markdown

重要:客観的かつ中立的なトーンを保ってください。

プロンプト最適化のコツ

プロンプトは実装後も継続的に改善するものです。以下を意識します:

1. ターゲット読者の明示
「初心者向けに」「技術者向けに」など、対象を明確にするとAIの出力がブレません。

2. 記事の長さを具体的に
「1000~1500字」と範囲指定することで、短すぎたり冗長になるのを防げます。

3. 禁止事項の明記
「推測や不確実な内容は避ける」など、品質管理を重視。

4. 出力フォーマットの指定
Markdown形式で返すよう指定すると、WordPress等に自動公開する際の処理が簡潔になります。

API コスト削減のテクニック

大規模クロール時のOpenAI API コスト削減:

方法1:ベクトルデータベース活用

初回クロール時のMarkdownをPinecone等のベクトルDBに格納し、LLMが必要な箇所のみ参照させることで、毎回のAPI呼び出しを削減。

方法2:バッチプロセッシング

複数記事をまとめて処理するPromptを作成し、1回のAPI呼び出しで複数記事を生成。

例:

以下の3つのニュース記事を日本語ブログ記事に変換。
各記事は「---」で区切られています。
各記事について同じ要件を適用してください。

記事1:
---
{{ $json[0].markdown }}

記事2:
---
{{ $json[1].markdown }}

実装上の注意点とトラブルシューティング

よくあるエラーと対応方法

エラー原因対応方法
CAPTCHA検出アクセス頻度が高いHeadless Browser + プロキシ設定
404エラーページが削除されたexcludeUrls設定で該当URLを除外
JavaScriptが実行されないRaw HTTPクローラー使用crawlerType: “adaptive”に変更
タイムアウトページが重いwaitForDynamicContent を増加(秒数UP)

レート制限への対策

外部サイト(OpenAI、Apify等)のレート制限を超えないため:

1. Waitノードの挿入
各バッチ処理間に90秒の待機を設定

After each batch: 90 seconds wait

2. バッチサイズの調整
Loop Over Items で「Batch Size: 5」に設定し、5ページずつ纏めて処理

3. 実行時間の分散
複数ワークフローを1日の異なる時間帯に実行

エラーハンドリングの実装

ワークフロー内の重要なステップ後にError nodeを設定:

失敗時の処理例

  • Slack/Discordに通知を送信
  • ログをファイルに記録
  • ワークフローを停止

まとめ

本記事では、n8nとApifyを使用して、ニュースサイトからの完全自動ブログ生成ワークフローを段階的に解説しました。

主な要点

  1. n8n × Apifyの組み合わせにより、ノーコードでプロフェッショナルな自動化を実現
  2. Website Content Crawlerの設定では「Adaptive」クローラーが費用効率面で最適
  3. MD5ハッシュによる重複排除で、同じ記事の二重取得を防止
  4. SQLiteデータベースでクロール履歴を管理し、1日周期実行に対応
  5. OpenAI統合でAIが記事を自動生成。プロンプト工夫でコスト削減も可能
  6. エラーハンドリングを実装することで、長期的に安定稼働するワークフローに

次に試すべきこと

段階1:n8nに無料登録し、Apifyノードをインストール

段階2:1つのニュースサイトで試験クロール(maxCrawlPages: 5に設定して低コスト実装)

段階3:クロール結果をローカルで確認し、Markdownフォーマットが正しいか検証

段階4:SQLiteデータベースを構築し、重複排除ロジックをテスト

段階5:OpenAIノードを統合し、ブログ記事の自動生成をテスト

段階6:本格運用に向けて、スケジュール設定、エラー処理、モニタリング環境を整備

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール