コンテンツにスキップ
X

Level 7 実践: トレンドからブログネタを自動収集する

概念・仕組みを先に理解したい方は Level 7 の概念ガイド を参照してください。


Puppeteer MCP(Model Context Protocol サーバー)を Claude Code に追加し、ブラウザ操作でトレンド記事を収集してブログ記事を自動生成します。ネタ探しにかかる時間をゼロに近づけられます。

対象読者: Level 6 まで完了しており、/blog スラッシュコマンドが動作している方。Node.js の基本操作に慣れていると理解しやすいです。

学習時間の目安: 読了 10分 + 実践 40分


Level 6 で PR 自動レビューが完成した。ブログ記事は /blog コマンドで量産できるが、ネタ探しに時間がかかっており、自動化が課題になっている。


.claude/settings.json に Puppeteer MCP サーバーを追加します。既存の GitHub MCP と並べた完全な設定を示します。

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
      "env": {
        "PUPPETEER_LAUNCH_OPTIONS": "{\"headless\": true, \"args\": [\"--no-sandbox\"]}"
      }
    }
  },
  "permissions": {
    "allow": [
      "mcp:github:*",
      "mcp:puppeteer:*"
    ]
  }
}

@modelcontextprotocol/server-puppeteer は npx 実行時に自動でダウンロードされます。事前インストールは不要です。

Claude Code を再起動して MCP サーバーが読み込まれたことを確認します。

# 一度終了して再起動
exit

claude

起動時のログに puppeteer MCP server started のような表示が出れば成功です。


Step 2: ブラウザ操作でトレンドを収集する

Section titled “Step 2: ブラウザ操作でトレンドを収集する”

Claude Code の対話モードで以下を順番に入力します。

Step 2-1: トレンド記事の収集

> dev.to/t/typescript のページを開いて今週のトレンド記事タイトルを10件取得してください。

Claude は Puppeteer MCP を使ってブラウザを起動し、ページのテキストコンテンツを解析します。出力例:

dev.to/t/typescript を開きました。

今週のトレンド記事(10件):
1. "TypeScript 5.5's Inferred Type Predicates Explained"
2. "Stop Using `any`: A Practical Guide to Unknown"
3. "Zod v4 Released: What's New for Runtime Validation"
4. "Branded Types in TypeScript for Domain Modeling"
5. "TypeScript Decorators Are Finally Stable"
6. "React 19 and TypeScript: New Hooks Typing Patterns"
7. "Building Type-Safe APIs with tRPC and Next.js 14"
8. "Why I Switched from Prisma to Drizzle ORM"
9. "TypeScript Performance Tips for Large Codebases"
10. "Satisfies Operator: When to Use It Over As"

Step 2-2: my-portfolio 向けの優先度付け

> my-portfolio のブログ(Next.js・TypeScript 中心)でカバーすべき上位3件を選んでください。

Claude の出力例:

my-portfolio のブログ方針(Next.js・TypeScript 中心)に基づいて選定しました。

## 優先度高(上位3件)

1. **"TypeScript 5.5's Inferred Type Predicates Explained"**
   理由: TypeScript の新機能で、Next.js プロジェクトにすぐ適用できる。
   想定タイトル案: 「TypeScript 5.5 の型述語推論で if 文が変わる」

2. **"React 19 and TypeScript: New Hooks Typing Patterns"**
   理由: React と TypeScript の組み合わせは my-portfolio の中心トピック。
   想定タイトル案: 「React 19 の新フックを TypeScript で型安全に使う」

3. **"Building Type-Safe APIs with tRPC and Next.js 14"**
   理由: Next.js 14 + TypeScript という my-portfolio の技術スタックに直結。
   想定タイトル案: 「tRPC + Next.js 14 で型安全フルスタック開発」

## 優先度低(今回はスキップ)

- "Zod v4 Released": 有用だが my-portfolio の現在の記事と重複する可能性がある
- "Why I Switched from Prisma to Drizzle ORM": データベース系で現在のブログ方針と外れる

Step 3: 自動収集・記事生成スクリプトの作成

Section titled “Step 3: 自動収集・記事生成スクリプトの作成”

収集からブログ記事生成までを一括実行する scripts/collect_and_blog.sh を作成します。

#!/usr/bin/env bash
# scripts/collect_and_blog.sh
# dev.to のトレンドを収集して /blog コマンドで記事を自動生成する

set -euo pipefail

BLOG_DIR="src/content/posts"
LOG_FILE="logs/collect_and_blog_$(date +%Y%m%d_%H%M%S).log"
mkdir -p logs

echo "=== ブログネタ自動収集・生成 ===" | tee "${LOG_FILE}"
echo "開始時刻: $(date)" | tee -a "${LOG_FILE}"
echo "" | tee -a "${LOG_FILE}"

# Step 1: Puppeteer MCP でトレンドを収集して JSON で出力
echo "Step 1: dev.to のトレンドを収集しています..." | tee -a "${LOG_FILE}"

TREND_PROMPT="dev.to/t/typescript を開いて今週のトレンド記事を10件取得し、
my-portfolio(Next.js・TypeScript 中心のブログ)向けに優先度の高い上位3件を選んでください。
出力は以下の JSON 形式のみで返してください(説明文は不要):

{
  \"articles\": [
    {\"rank\": 1, \"title\": \"元記事タイトル\", \"blog_title\": \"日本語の記事タイトル案\", \"reason\": \"選定理由\"},
    {\"rank\": 2, \"title\": \"元記事タイトル\", \"blog_title\": \"日本語の記事タイトル案\", \"reason\": \"選定理由\"},
    {\"rank\": 3, \"title\": \"元記事タイトル\", \"blog_title\": \"日本語の記事タイトル案\", \"reason\": \"選定理由\"}
  ]
}"

TREND_JSON=$(echo "${TREND_PROMPT}" | claude --print --dangerously-skip-permissions)
echo "収集結果:" | tee -a "${LOG_FILE}"
echo "${TREND_JSON}" | tee -a "${LOG_FILE}"
echo "" | tee -a "${LOG_FILE}"

# Step 2: JSON をパースして各記事を生成
echo "Step 2: ブログ記事を生成しています..." | tee -a "${LOG_FILE}"

# jq で記事タイトルを抽出してループ
TITLES=$(echo "${TREND_JSON}" | jq -r '.articles[].blog_title' 2>/dev/null || echo "")

if [ -z "${TITLES}" ]; then
  echo "ERROR: JSON のパースに失敗しました。ログを確認してください。" | tee -a "${LOG_FILE}"
  exit 1
fi

COUNT=0
while IFS= read -r TITLE; do
  COUNT=$((COUNT + 1))
  echo "  記事 ${COUNT}: ${TITLE}" | tee -a "${LOG_FILE}"

  BLOG_PROMPT="/blog ${TITLE}"
  echo "${BLOG_PROMPT}" | claude --print --dangerously-skip-permissions >> "${LOG_FILE}" 2>&1

  echo "  完了" | tee -a "${LOG_FILE}"
  echo "" | tee -a "${LOG_FILE}"

  # API レート制限を避けるため少し待つ
  sleep 3
done <<< "${TITLES}"

echo "=== 完了 ===" | tee -a "${LOG_FILE}"
echo "生成された記事数: ${COUNT}" | tee -a "${LOG_FILE}"
echo "ログ: ${LOG_FILE}" | tee -a "${LOG_FILE}"

実行権限を付与して実行します。

chmod +x scripts/collect_and_blog.sh
./scripts/collect_and_blog.sh

実行完了後、src/content/posts/ に新しい記事ファイルが生成されていることを確認します。

ls -lt src/content/posts/ | head -5

# 最新の記事を確認
LATEST=$(ls -t src/content/posts/*.md 2>/dev/null | head -1)
if [ -n "${LATEST}" ]; then
  head -20 "${LATEST}"
fi

ローカルで確認します。

npm run dev
# http://localhost:4321/blog でブログ一覧を確認

スクレイピングを行う前に以下を確認してください。

確認項目内容
robots.txtdev.to/robots.txt でクローリングが許可されているパスを確認する
利用規約サービスの利用規約でスクレイピングの可否を確認する
アクセス頻度短時間に大量のリクエストを送らない(スクリプト内の sleep 3 は最低限の配慮)
著作権収集した記事タイトルはアイデアの参考にとどめ、内容はオリジナルで書く

Puppeteer MCP はブラウザを直接操作するため、robots.txt での制限を技術的にはバイパスできますが、サービスの利用規約を遵守することが求められます。


  • .claude/settings.json に Puppeteer MCP サーバーが追加された
  • scripts/collect_and_blog.sh が追加され、トレンド収集から記事生成までを一括実行できる
  • logs/ ディレクトリに実行ログが保存される
  • src/content/posts/ にトレンドベースのブログ記事が自動生成された
my-portfolio/
├── .claude/
│   └── settings.json         # ← Puppeteer MCP を追加
├── scripts/
│   ├── review_pr.sh
│   └── collect_and_blog.sh   # ← 新規追加
├── logs/                     # ← 新規追加
│   └── collect_and_blog_*.log
├── src/
│   └── content/
│       └── posts/
│           ├── typescript-type-inference.md   # 既存
│           ├── nextjs-app-router.md           # 既存
│           ├── react-useeffect.md             # 既存
│           └── typescript-55-inferred-*.md   # ← 新規生成
└── ...

Level 8 実践: 3機能を Git worktree で並列実装する