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?

X(Twitter)投稿をPythonで毎日自動化する方法【Gemini×Claude×Tweepy】

0
Posted at

はじめに

こんにちは。ITフィールドセールスをしている長井洸太です。

毎日X(Twitter)に投稿し続けることが、エンジニアや経営者との接点づくりに有効だと感じています。ただ「毎日ネタを考えて投稿する」のは正直しんどい。

そこで今回は、世界中のニュースをGeminiで収集 → ClaudeでX投稿文を5パターン生成 → Tweepyで自動投稿 する仕組みを作ったので、コードと手順を共有します。

実際に今日も使ったばかりです。


作ったもの

ニュース収集(BBC・Reuters・TechCrunch・Reddit など10ソース)
    ↓ Gemini 2.5 Flash で要約・選定
Claude Haiku で投稿文を5パターン生成
    ├── 反論型(月曜向け)
    ├── 速報型
    ├── 問いかけ型
    ├── 学び共有型
    └── 一言格言型
    ↓
Markdown に下書き保存 → 確認 → Tweepy で投稿

必要なもの

Python 3.10+
anthropic        # Claude API
google-genai     # Gemini API
tweepy           # X API
feedparser       # RSS取得
beautifulsoup4   # スクレイピング
python-dotenv    # 環境変数管理
requests
pip install anthropic google-genai tweepy feedparser beautifulsoup4 python-dotenv requests

.env に設定するキー

CLAUDE_API_KEY=sk-ant-...
GEMINI_API_KEY=AIza...
TWITTER_API_KEY=your_key
TWITTER_API_SECRET=your_secret
TWITTER_ACCESS_TOKEN=your_token
TWITTER_ACCESS_TOKEN_SECRET=your_token_secret

X APIは Basic プラン(月100ドル) が必要です。Free プランは投稿のみ可能ですが、ユーザー検索などに制限があります。


コード

① ニュース収集

import feedparser
import requests
from bs4 import BeautifulSoup

def fetch_rss(name, url, limit=3):
    feed = feedparser.parse(url)
    return [f"- {e.get('title','')}  ({e.get('link','')})" for e in feed.entries[:limit]]

def fetch_reddit_hot(subreddit, limit=3):
    url = f"https://www.reddit.com/r/{subreddit}/hot.json?limit={limit}"
    resp = requests.get(url, timeout=10, headers={"User-Agent": "Mozilla/5.0"})
    data = resp.json()
    results = []
    for post in data["data"]["children"][:limit]:
        p = post["data"]
        title = p.get("title", "")
        link  = p.get("url", f"https://reddit.com{p.get('permalink','')}")
        results.append(f"- {title}  ({link})")
    return results

def collect_news():
    bbc      = fetch_rss("BBC",        "http://feeds.bbci.co.uk/news/rss.xml", 4)
    tc       = fetch_rss("TechCrunch", "https://techcrunch.com/feed/", 3)
    verge    = fetch_rss("The Verge",  "https://www.theverge.com/rss/index.xml", 3)
    yahoo_jp = fetch_rss("Yahoo Japan","https://news.yahoo.co.jp/rss/topics/top-picks.xml", 4)
    reddit   = fetch_reddit_hot("technology", 3)

    return "\n".join(bbc + tc + verge + yahoo_jp + reddit)

② Geminiで要約・選定

from google import genai

gemini_client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))

def summarize_news(raw_news: str) -> str:
    prompt = f"""
以下のニュースから、X(Twitter)で最も反応されそうなAI・テック関連ニュースを3件選んでください。

【収集済みニュース】
{raw_news}

【出力形式】
タイトル:〇〇
概要:1行
URL:〇〇
バズりそうな理由:1行
"""
    resp = gemini_client.models.generate_content(
        model="gemini-2.5-flash",
        contents=prompt
    )
    return resp.text

③ ClaudeでX投稿文を5パターン生成

import anthropic

claude_client = anthropic.Anthropic(api_key=os.getenv("CLAUDE_API_KEY"))

X_PATTERNS = [
    {"name": "反論型",    "rule": "通説を1行で否定→根拠→問いかけ。140文字以内。"},
    {"name": "速報型",    "rule": "【速報】ラベル+核心→重要性→出典。140文字以内。"},
    {"name": "問いかけ型", "rule": "問いで始める→背景1〜2文→二択で締め。140文字以内。"},
    {"name": "学び共有型", "rule": "「正直に言う。」一人称→体験→共感の問い。140文字以内。"},
    {"name": "一言格言型", "rule": "本質を1〜2行に凝縮。根拠を括弧書きで添える。100文字以内。"},
]

def generate_tweet(news_summary: str, pattern: dict) -> str:
    prompt = f"""
以下のニュースをもとに、X投稿文を1つ作成してください。

【ニュース】
{news_summary}

【投稿スタイル:{pattern['name']}{pattern['rule']}

【ルール】
・日本語280文字以内(ハッシュタグ含む)
・Markdown記号(**など)は使わない
・出典URLは末尾に「出典:URL」形式で1つのみ
・投稿文のみ出力

投稿文:
"""
    resp = claude_client.messages.create(
        model="claude-haiku-4-5-20251001",
        max_tokens=300,
        messages=[{"role": "user", "content": prompt}],
    )
    return resp.content[0].text.strip()

④ Tweepyで投稿

import tweepy

def get_x_client():
    return tweepy.Client(
        consumer_key=os.getenv("TWITTER_API_KEY"),
        consumer_secret=os.getenv("TWITTER_API_SECRET"),
        access_token=os.getenv("TWITTER_ACCESS_TOKEN"),
        access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"),
    )

def post_tweet(text: str):
    client = get_x_client()
    response = client.create_tweet(text=text)
    tweet_id = response.data["id"]
    print(f"✅ 投稿完了: https://x.com/i/web/status/{tweet_id}")
    return tweet_id

⑤ まとめて実行

from pathlib import Path
from datetime import datetime

def main():
    # 1. ニュース収集
    raw_news = collect_news()

    # 2. Geminiで要約
    news_summary = summarize_news(raw_news)

    # 3. 5パターン生成して下書き保存
    date_str = datetime.now().strftime("%Y-%m-%d")
    draft_path = Path(f"Earning/x-posts/{date_str}_draft.md")
    draft_path.parent.mkdir(parents=True, exist_ok=True)

    lines = [f"# X投稿下書き ({date_str})\n", "selected_pattern: 1\n\n---\n"]
    for i, pattern in enumerate(X_PATTERNS, 1):
        tweet = generate_tweet(news_summary, pattern)
        lines += [f"## パターン{i}{pattern['name']}\n", tweet, "\n\n---\n"]

    draft_path.write_text("\n".join(lines), encoding="utf-8")
    print(f"💾 下書き保存: {draft_path}")

    # 4. 確認後に投稿(パターン1を使用)
    # post_tweet(tweet_text)  # 確認後にコメントアウトを外す

if __name__ == "__main__":
    main()

使い方

# 下書きを生成して確認
python scripts/x/x_post_generator.py --generate

# 生成した下書きを投稿(パターン1を選択)
python scripts/x/x_post_generator.py --publish --draft-id 2026-06-25

# 生成と投稿を一気に(確認あり)
python scripts/x/x_post_generator.py --full-auto

# AIスレッド(6ツイート)を生成して投稿
python scripts/x/x_post_generator.py --thread

出力サンプル(今日の生成結果)

============================================================
X(Twitter) 投稿自動化ツール
============================================================
📡 世界トレンドニュースを収集中(10ソース)...
✅ 世界トレンド分析完了

✍️  5パターンをClaudeで生成中...
  ✅ 反論型(204文字)
  ✅ 速報型(185文字)
  ✅ 問いかけ型(181文字)
  ✅ 学び共有型(242文字)
  ✅ 一言格言型(141文字)

💾 下書き保存: Earning/x-posts/2026-06/2026-06-25_draft.md

実際に今日生成された反論型はこちらです。

米国の半導体覇権独占はもう終わり🔚 TechCrunchによると、欧州がワシントンの
政策に本気で反発し始めたとのこと。サプライチェーンは多極化していく運命にある。
グローバル競争の時代が来ると思いませんか?

#半導体戦争 #地政学リスク

出典:https://techcrunch.com/2026/06/24/europe-is-pushing-back-on-washingtons-chip-war/

やってみてわかったこと(セールス視点)

ニュースを選ぶAIと、文章を書くAIを分けたのが正解でした。

最初はClaudeに「ニュース収集から投稿文まで全部やって」と渡していたのですが、ハルシネーション(存在しないURLを作る)が頻発しました。

そこで役割を分けました。

  • Gemini → ネット検索・RSS収集・URL検証(実在するURLのみ扱う)
  • Claude → 文章生成(渡された情報から表現を磨く)

この分業にしてから、URLの捏造がゼロになりました。AIにも「得意・不得意」があります。


おわりに

このスクリプトを使って毎日X投稿を続けることで、エンジニアや経営者からのフォロー・DMが増えています。

「セールスがAIを使ってこんなことやってるのか」と興味を持ってもらえることが多いです。

X(@kotajobs0)でもAI業務自動化の話を毎日発信しています。よかったらフォローしてください。


関連記事

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?