0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

noteで稼ぎたい人向け、AIで仕込む『投稿仕組み化』5ステップ

0
Posted at

TL;DR

note等での定期投稿を自動化・効率化するための仕組み化戦略を紹介します。トピック収集→記事管理→生成→レビュー→エンゲージメント対応まで、AIと人手を組み合わせて手作業を50%削減できます。Claude Code + YAML管理 + スクリプト自動化で実装可能です。


なぜ投稿を仕込み化するのか

毎日複数の記事を継続的に投稿する際、最大の課題は「時間」です。トレンド情報を常時チェック→ネタ帳管理→下書き作成→公開確認→コメント対応という一連のフローを、すべて手作業で回すことは現実的ではありません。

本来やるべき仕事は「何を書くか」「本当にこの内容でいいか」という判断と、「読者との関係構築」です。それ以外のタスク(情報収集、ファイル管理、定型的な返信)は自動化すれば、月収向上に直結する時間が確保できます。


全体アーキテクチャ

┌─────────────────┐
│ トピック源      │ (X API, Google検索)
└────────┬────────┘
         ↓
┌─────────────────┐
│ JSONプール管理  │ (構造化ファイル)
└────────┬────────┘
         ↓
┌─────────────────┐
│ 下書き生成      │ (Claude API + プロンプト)
└────────┬────────┘
         ↓
┌─────────────────┐
│ 人手レビュー    │ (Discord通知)
└────────┬────────┘
         ↓
┌─────────────────┐
│ 自動投稿        │
└────────┬────────┘
         ↓
┌─────────────────┐
│ エンゲージメント│ (自動スキ・返信)
└─────────────────┘

ステップ1:トピック源を自動収集

毎朝JSONファイルにトピック候補を更新するスクリプトです。X API + Google検索を並列実行します。

import json
from datetime import datetime
from anthropic import Anthropic

client = Anthropic()

def collect_topics():
    """X + Google検索からトピック収集"""
    topics = []
    
    # X API (無料枠でキーワード検索)
    x_queries = ["Claude Code", "AI副業", "個人開発"]
    for query in x_queries:
        # X API実装(簡略)
        topics.extend(search_x_trends(query))
    
    # Google検索スクレイピング
    google_results = search_google(
        queries=["エンジニア 副業トレンド", "AI ツール比較"],
        top_k=10
    )
    topics.extend(google_results)
    
    # JSON保存
    with open("topics.json", "w", encoding="utf-8") as f:
        json.dump({"topics": topics, "updated_at": datetime.now().isoformat()}, f, indent=2)
    
    return topics

def search_x_trends(query: str):
    """X検索APIからトレンド取得"""
    return [
        {
            "id": f"x_{i}",
            "title": f"{query} related topic {i}",
            "source": "x_trending",
            "status": "new",
            "created_at": datetime.now().isoformat(),
            "reference_url": f"https://x.com/search?q={query}"
        }
        for i in range(5)
    ]

def search_google(queries: list, top_k: int = 10):
    """Google検索結果を構造化"""
    results = []
    for query in queries:
        #実装例:BeautifulSoup + Seleniumで取得
        results.append({
            "id": f"google_{query}",
            "title": f"検索: {query}の最新情報",
            "source": "google_search",
            "status": "new",
            "created_at": datetime.now().isoformat(),
            "reference_url": f"https://www.google.com/search?q={query}"
        })
    return results

実装のコツ

  • X API無料枠は月450リクエスト、キーワード指定で毎朝1回実行
  • Google検索スクレイピングはセッション分散、レート制限に注意
  • 毎朝5時に定期実行(cron or GitHub Actions推奨)

ステップ2:記事プールを構造化管理

YAML/JSONで統一管理し、スクリプトが自動で進捗を追跡できます。

topics:
  - id: topic_001
    title: Claude Codeの月額費用を副業で回収する戦略
    source: x_trending
    status: new
    created_at: 2026-05-16T09:00:00Z
    target_tone: business
    reference_url: https://x.com/...
    tags: [Claude, 副業, 個人開発]

  - id: topic_002
    title: 自動投稿ツールで失敗する理由
    source: google_search
    status: draft
    created_at: 2026-05-15T10:00:00Z
    target_tone: educational
    reference_url: https://example.com/...
    draft_path: drafts/topic_002.md
    tags: [自動化, note, 失敗事例]

  - id: topic_003
    title: XXX
    source: x_trending
    status: review
    created_at: 2026-05-14T14:00:00Z
    target_tone: analytical
    draft_path: drafts/topic_003.md
    reviewer_feedback: null

ステータス遷移:newdraftreviewpublished

def update_topic_status(topic_id: str, new_status: str):
    """トピックのステータスを更新"""
    with open("topics.yaml", "r") as f:
        data = yaml.safe_load(f)
    
    for topic in data["topics"]:
        if topic["id"] == topic_id:
            topic["status"] = new_status
            break
    
    with open("topics.yaml", "w") as f:
        yaml.dump(data, f)

ステップ3:下書き生成プロンプトの設計

プロンプトテンプレートを固定化すると、出力ブレが劇的に減ります。

def generate_draft(topic: dict) -> str:
    """Claude APIで下書き生成"""
    
    system_prompt = """あなたはnoteのテクノロジー・副業領域の執筆者です。

【読者層】
- エンジニア(Web/バックエンド主体)
- 副業志向の個人開発者
- スタートアップ従事者

【禁止事項】
- 具体的な売上数値を根拠なく記載しない
- 個人の経験則を普遍的真実として述べない
- 商品紹介に見えるような記述

【構成】
1. 冒頭:実例 or 問題提示(50字以内)
2. 本論:3~4段落で具体的な理由・背景・実装例
3. 結論:示唆的に終わる(読者の次のアクションが見える)

【文字数】1200字程度
【トーン】敬体。淡々と事実ベース。"""
    
    user_prompt = f"""
【記事タイトル】
{topic['title']}

【トーン】
{topic['target_tone']}

【参考URL / 背景】
{topic.get('reference_url', 'なし')}

【タグ】
{', '.join(topic.get('tags', []))}

上記を踏まえて下書きを生成してください。
"""
    
    message = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=2000,
        system=system_prompt,
        messages=[
            {"role": "user", "content": user_prompt}
        ]
    )
    
    draft = message.content[0].text
    
    # 下書きを保存
    draft_path = f"drafts/{topic['id']}.md"
    with open(draft_path, "w", encoding="utf-8") as f:
        f.write(draft)
    
    return draft

プロンプト設計の要点

  • 読者層を明確に指定
  • 禁止事項を列挙(AIの出力を絞る)
  • 構成を型として示す
  • トーン・文字数を固定

ステップ4:レビューと公開承認フロー

ここは絶対に自動化しません。Discord通知で人間が判定します。

import discord
import json

class DiscordReviewBot:
    def __init__(self, token: str, channel_id: int):
        self.token = token
        self.channel_id = channel_id
    
    async def notify_review_required(self, topic: dict, draft: str):
        """レビュー必要通知をDiscordへ"""
        intents = discord.Intents.default()
        client = discord.Client(intents=intents)
        
        @client.event
        async def on_ready():
            channel = client.get_channel(self.channel_id)
            
            message = f"""
📝 **レビュー待ちの記事があります**

【タイトル】
{topic['title']}

【タグ】
{', '.join(topic.get('tags', []))}

【下書き(先頭300字)】
{draft[:300]}...

【判定】
✅ 公開OK
❌ 修正が必要
🔄 別のプロンプトで再生成
"""
            
            await channel.send(message)
            await client.close()
        
        await client.start(self.token)
    
    def set_review_status(self, topic_id: str, status: str, feedback: str = ""):
        """Discord上の返答をもとにステータス更新"""
        with open("topics.yaml", "r") as f:
            data = yaml.safe_load(f)
        
        for topic in data["topics"]:
            if topic["id"] == topic_id:
                topic["status"] = status
                topic["reviewer_feedback"] = feedback
                break
        
        with open("topics.yaml", "w") as f:
            yaml.dump(data, f)

運用フロー

  1. status: review のトピックを毎朝チェック
  2. Discordで通知(下書き先頭300字)
  3. 人間が ✅ または ❌ をリアクション
  4. スクリプトがステータス更新

ステップ5:エンゲージメント自動巡回

スキ返し・フォローバックを自動化し、時間対効果を高めます。

def auto_engagement_loop():
    """24時間以内の自投稿に対するエンゲージメント自動処理"""
    
    # 過去24時間の自投稿取得(note API or Selenium)
    my_posts = fetch_my_recent_posts(hours=24)
    
    for post in my_posts:
        print(f"Processing: {post['title']}")
        
        # コメント取得
        comments = fetch_comments(post['id'])
        
        for comment in comments:
            # 既に返信済みなら スキップ
            if is_replied(comment['id']):
                continue
            
            # スキ返し
            like_comment(comment['id'])
            print(f"  ❤️ Liked comment: {comment['id']}")
            
            # 返信テンプレで自動返答
            reply_text = generate_reply_from_template(
                commenter_name=comment['author'],
                comment_content=comment['text'],
                post_title=post['title']
            )
            reply_comment(comment['id'], reply_text)
            print(f"  💬 Replied: {comment['id']}")
        
        # フォロー者の自動フォローバック
        new_followers = fetch_new_followers()
        for follower in new_followers:
            if not is_following(follower['id']):
                follow_user(follower['id'])
                print(f"  👥 Followed back: {follower['name']}")

def generate_reply_from_template(commenter_name: str, comment_content: str, post_title: str) -> str:
    """テンプレベースの返信生成"""
    
    # 簡単な分類
    if any(word in comment_content for word in ["ありがとう", "参考になった", "勉強になった"]):
        template = f"@{commenter_name} こちらこそ、コメントありがとうございます!こういった反応をもらえると、執筆の励みになります。"
    elif any(word in comment_content for word in ["質問", "教えて", "どう"]):
        template = f"@{commenter_name} 良い質問ですね。別記事で掘り下げたいと思います。フォローしていただければ更新通知が届きます!"
    else:
        template = f"@{commenter_name} コメントありがとうございました。{post_title}について、さらに深掘りしたネタがあれば記事にします!"
    
    return template

自動化の限界

  • テンプレート返信は「感謝」「質問対応」など基本パターンのみ
  • 複雑な議論・クレーム対応は人手で
  • スキ返しは時間対効果が高い(1分で100件可能)

つまづきポイント

1. X API のレート制限

無料枠は月450リクエスト。毎朝1クエリで30日で30リクエスト程度なので問題ありませんが、複数キーワード×複数アカウントだと上限に達します。対策:アカウント分散 or 有料プランへ。

2. Google検索スクレイピングの検出

短時間に大量リクエストするとブロックされます。対策:

  • ユーザーエージェント分散
  • リクエスト間に2~3秒の遅延挿入
  • Cloudflare対応(playwright推奨)

3. プロンプトテンプレートの「飽き」

同じプロンプトを長く使うと出力パターンが固定化します。対策:月1回、フィードバックを踏まえてプロンプト改定。

4. Claude API の コスト

月1000投稿なら、入出力合計で月200~500円程度。想定外コストではありませんが、大量生成の場合は事前に計算してください。


まとめ

noteで継続的に月収を狙う場合、「毎日人力で3本書く」はスケーリングしません。本当に重要な仕事(何を書くか / 品質判定 / 読者関係構築)に集中し、情報収集・定型処理・エンゲージメント定型対応はAIに任せることで、時間効率が2~3倍改善します。

  • トピック源の自動収集:朝30分削減
  • 下書き生成:1本30分→5分
  • エンゲージメント自動化:毎日30分削減

結果、本当に書く・考えるべき時間に週5~7時間を確保できます。


さらに詳しい実装手順はnoteで公開中

この記事では概要のみ紹介しました。実装の完全手順・プロンプト全文・運用ノウハウ・エラーハンドリングの工夫は以下のnoteで公開しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?