Claude APIでブログ記事の下書きを自動生成する方法

ブログ記事を書くのが億劫な理由の多くは「0から書き始める」ことのしんどさだ。Claude APIを使えば、テーマを与えるだけで構成と下書きを自動生成できる。この記事では実際に私が使っているパイプラインを紹介する。

全体の構成

テーマ・キーワード入力
      ↓
Claude APIで構成案生成
      ↓
構成案を人間がレビュー・修正
      ↓
Claude APIで本文生成
      ↓
Markdownファイルとして保存
      ↓
WordPressに下書き投稿

手を動かすのは「構成案のレビュー・修正」と「最終確認」だけ。それ以外はスクリプトが自動でやってくれる。

必要なもの

  • Python 3.10以上
  • Anthropic APIキー(pip install anthropic
  • python-dotenv
pip install anthropic python-dotenv

Step 1: 構成案を生成する

まずテーマを受け取って記事の構成案を生成するスクリプトを作る。

import anthropic
import json
from pathlib import Path

def generate_outline(theme: str, target_length: int = 2000) -> dict:
    """記事の構成案を生成する"""
    client = anthropic.Anthropic()

    prompt = f"""
あなたはプロの技術ブロガーです。以下のテーマで技術ブログ記事の構成案を作成してください。

テーマ: {theme}
目標文字数: {target_length}文字

以下のJSON形式で返してください:
{{
    "title": "記事タイトル",
    "slug": "english-slug",
    "sections": [
        {{
            "heading": "h2見出し",
            "points": ["書くべき内容1", "書くべき内容2"]
        }}
    ],
    "tags": ["タグ1", "タグ2"]
}}
"""

    message = client.messages.create(
        model="claude-3-7-sonnet-20250219",
        max_tokens=1024,
        system="必ずJSON形式のみで返してください。説明文は含めないでください。",
        messages=[{"role": "user", "content": prompt}]
    )

    return json.loads(message.content[0].text)


# 使用例
outline = generate_outline("PythonでWordPress REST APIを自動化する方法")
print(json.dumps(outline, ensure_ascii=False, indent=2))

Step 2: 本文を生成する

構成案を承認したら、各セクションの本文を生成する。

def generate_section(heading: str, points: list[str], context: str = "") -> str:
    """各セクションの本文を生成する"""
    client = anthropic.Anthropic()

    points_text = "\n".join(f"- {p}" for p in points)

    prompt = f"""
以下のセクションの本文を書いてください。

見出し: {heading}
含めるべき内容:
{points_text}

条件:
- 一人称(私)で書く
- 実体験や具体例を含める
- コードがある場合はPythonかJavaScriptで書く
- 200〜400文字程度

{f"記事全体の文脈: {context}" if context else ""}
"""

    message = client.messages.create(
        model="claude-3-7-sonnet-20250219",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    )

    return message.content[0].text


def generate_article(outline: dict) -> str:
    """構成案から記事全体を生成する"""
    sections = []

    for section in outline["sections"]:
        content = generate_section(
            heading=section["heading"],
            points=section["points"]
        )
        sections.append(f"## {section['heading']}\n\n{content}")

    return "\n\n".join(sections)

Step 3: Markdownファイルとして保存する

フロントマター付きのMarkdownファイルとして保存する。

def save_draft(outline: dict, content: str, output_dir: str = "articles/drafts") -> Path:
    """下書きをMarkdownファイルとして保存する"""
    Path(output_dir).mkdir(parents=True, exist_ok=True)

    tags_str = ", ".join(f'"{t}"' for t in outline["tags"])

    frontmatter = f"""---
title: {outline["title"]}
slug: {outline["slug"]}
category: AI・機械学習
tags: [{tags_str}]
status: draft
---

"""

    filepath = Path(output_dir) / f"{outline['slug']}.md"
    filepath.write_text(frontmatter + content, encoding="utf-8")

    print(f"保存しました: {filepath}")
    return filepath

Step 4: 全部つなげて実行する

def main():
    theme = input("記事のテーマを入力: ")

    print("構成案を生成中...")
    outline = generate_outline(theme)

    print("\n--- 構成案 ---")
    print(f"タイトル: {outline['title']}")
    for s in outline["sections"]:
        print(f"  ## {s['heading']}")

    confirm = input("\nこの構成で本文を生成しますか? (y/n): ")
    if confirm.lower() != "y":
        print("キャンセルしました")
        return

    print("本文を生成中...")
    content = generate_article(outline)

    filepath = save_draft(outline, content)
    print(f"\n完成: {filepath}")


if __name__ == "__main__":
    main()

コスト感

Claude 3.7 Sonnet(claude-3-7-sonnet-20250219)を使った場合、2000文字の記事1本あたりのAPIコストは大体$0.01〜0.03程度。月50本書いても$1〜1.5。

入力トークンは比較的安いので、詳細なsystem promptを書いてもコストへの影響は軽微。

実際に使ってみた感想

このパイプラインで生成した下書きを使って記事を書いていると、「ゼロから書く」負担が大幅に減った。生成される文章はそのまま使えるものではなく、あくまで「下書き」として手を加える必要があるが、構成と各セクションの骨格が揃った状態からスタートできるのが大きい。

特に効果的だったのは構成案の生成。自分で考えると1つの視点に偏りがちだが、AIが生成した構成案には「あ、この観点を忘れてた」という気づきが含まれることが多い。

まとめ

Claude APIを使った記事下書き生成パイプラインの実装手順を紹介した。要点をまとめると:

  • 構成案と本文生成を分けて、人間のレビューポイントを設ける
  • system promptで出力形式(JSON)を厳密に指定する
  • 生成コンテンツは「下書き」として扱い、必ず人間が加筆修正する

このスクリプトはGitHubに公開予定。興味があれば参考にしてほしい。