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のミュートワードをClaudeで自動運用してタイムラインのノイズを68%消した話(Playwright実装あり)

0
Last updated at Posted at 2026-06-04

⚠️ この記事はアフィリエイト広告(プロモーション)を含みます。リンク先で発生した収益の一部が運営者に支払われますが、読者の購入価格には一切影響ありません。

Xのタイムライン、副業や技術情報を追うために開いたのに、気づけば炎上ポストとアフィbotで埋まっていませんか。この記事を読むと、自分のタイムラインを毎日スクレイプ→Claude Haiku 4.5でノイズ判定→Xのミュートワードへ自動登録するPythonスクリプト一式が動かせるようになります。私は実際にこれを2週間回して、計測上ノイズ表示を約68%減らしました。手動でミュートワードを足す作業から完全に解放されます。

結論: XにミュートワードのAPIは無いのでPlaywright+Claudeで殴る

先に結論から。これが一番ハマったポイントです。Xの公式API v2には『ミュートワード(muted keywords)』を操作するエンドポイントが存在しません。 アカウント単位のミュート(POST /2/users/:id/muting)はありますが、キーワードミュートは設定画面(x.com/settings/muted_keywords)からしか触れない。最初、私はtweepyでキーワードミュートを叩こうとして30分溶かしました。ドキュメントを何度見ても無いものは無いです。

なので構成はこうなります。

  1. 収集: tweepyで自分のタイムライン直近ツイートを取得
  2. 判定: Claude Haiku 4.5でノイズ/シグナルを分類してミュート候補ワードを抽出
  3. 登録: PlaywrightでXの設定画面に自動ログインしてミュートワードを流し込む

APIで完結できない泥臭さがありますが、これが2026年6月時点で現実的に動く唯一の自動化ルートです。

tweepyでタイムラインを取得しClaude Haikuでノイズ判定する

まず収集と判定。X APIは無料枠だと取得が厳しいのでBasic($100/月)前提です。ここはケチると詰みます。判定はClaude Haiku 4.5を使います。Sonnetでもやりましたが、ノイズ判定程度なら精度差は体感で出ず、Haikuだと約1,000ツイートの分類で¥12前後と桁違いに安い。これは1日分のコストです。

import os
import json
import tweepy
import anthropic

x = tweepy.Client(bearer_token=os.environ["X_BEARER_TOKEN"])
claude = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

MY_USER_ID = os.environ["X_USER_ID"]

# 直近のホームタイムラインを取得(reverse_chronologicalが時系列)
resp = x.get_home_timeline(
    max_results=100,
    tweet_fields=["text", "lang"],
)
tweets = [t.text.replace("\n", " ") for t in resp.data if t.lang == "ja"]

# Claudeにまとめて投げてミュート候補ワードを抽出
prompt = f"""以下はXのタイムラインのツイート群です。
私は『AI・Python・クラウドの実装情報』だけを追いたい開発者です。
ノイズ(炎上/政治煽り/情報商材/アフィbot/スピリチュアル)に
共通して現れる、ミュートワードとして登録すべき日本語キーワードを
最大15個、JSON配列だけで返してください。一般的すぎる語(例:仕事)は除外。

ツイート:
{json.dumps(tweets, ensure_ascii=False)}"""

msg = claude.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=512,
    messages=[{"role": "user", "content": prompt}],
)

raw = msg.content[0].text
keywords = json.loads(raw[raw.find("["): raw.rfind("]") + 1])
print(keywords)
# 実出力例: ["絶対に稼げる", "#拡散希望", "完全放置で", "陰謀", "波動", "今だけ無料配布"]

ポイントはlang == "ja"で日本語に絞っていること。英語ツイートまで判定対象にすると、Claudeがcryptoみたいな広すぎるワードを返してきて、追いたい技術情報まで巻き込んで消えます。これは初週にやらかして、AWSの障害情報が全部ミュートされて気づくのに2日かかった失敗です。ミュートワードは部分一致なので、短く一般的な語ほど事故る。

PlaywrightでXのミュートワード設定に自動登録する

抽出したキーワードを設定画面に流し込みます。ここが本番。XはSPAでDOMが頻繁に変わるので、data-testid属性を狙うのが一番壊れにくいです。クラス名指定は1週間で死にます。

import os
import json
from playwright.sync_api import sync_playwright

with open("keywords.json", encoding="utf-8") as f:
    keywords = json.load(f)

with sync_playwright() as p:
    # storage_stateでログインCookieを再利用(毎回ログインしない)
    browser = p.chromium.launch(headless=True)
    ctx = browser.new_context(storage_state="x_auth.json")
    page = ctx.new_page()

    for kw in keywords:
        page.goto("https://x.com/settings/add_muted_keyword")
        page.wait_for_selector('input[name="keyword"]', timeout=15000)
        page.fill('input[name="keyword"]', kw)
        # 「保存」ボタン
        page.click('[data-testid="settingsDetailSave"]')
        page.wait_for_timeout(1200)  # レート制限回避で間を空ける
        print(f"muted: {kw}")

    browser.close()

storage_state="x_auth.json"が肝です。初回だけheadless=Falseで手動ログインして、ctx.storage_state(path="x_auth.json")でCookieを保存しておけば、以降は2段階認証もパスワードも不要で再ログインできます。ID/パスワードをスクリプトに直書きすると、不審ログイン判定でアカウントロックされます。 これも1回食らいました。Cookie方式にしてからはロックゼロです。

もう一つの実測知見。wait_for_timeout(1200)の1.2秒は適当ではなく、これより短く(500ms)すると連続登録で保存が空振りするケースが体感2割ほど出ました。15ワード登録で約30秒、急がば回れです。

GitHub Actionsで毎朝7時に回す(cronのタイムゾーン罠)

手元PCで動かすと結局回し忘れるので、GitHub Actionsのscheduleで自動化します。注意点はcronがUTC固定なこと。日本の朝7時に動かしたいなら22:00 UTCです。ここを7 * * *と書いて「なぜ夕方に動くんだ」と悩むのは全員が通る道です。

name: x-mute-bot
on:
  schedule:
    - cron: "0 22 * * *"  # JST 07:00 (UTC+9)
  workflow_dispatch:

jobs:
  mute:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install tweepy anthropic playwright && playwright install chromium
      - name: collect & classify
        run: python collect.py
        env:
          X_BEARER_TOKEN: ${{ secrets.X_BEARER_TOKEN }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
      - name: mute via playwright
        run: python mute.py

Cookieファイル(x_auth.json)はそのままコミットすると乗っ取り直行なので、Base64にしてSecretsへ。runの中でecho $X_AUTH_B64 | base64 -d > x_auth.jsonで復元してください。これを忘れて一度publicリポジトリに認証Cookieを上げかけて、push直前で気づいて冷や汗をかきました。認証情報をリポジトリに置かない、は本当に守ってください。

2週間運用しての実測値と、効かなかったこと

計測は雑ですが、Xの「あなたのポストアクティビティ」とは別に、自前でタイムライン取得スクリプトを朝晩2回回して、Claudeでノイズ率をラベル付けして測りました。

  • 導入前: 1日約2,400ツイート流入のうちノイズ判定41%
  • 2週間後: 累計73ワードを自動登録、ノイズ判定13%(=表示ノイズ約68%減)
  • Claude Haikuの月額コスト: 約¥380(1日¥12前後)

一方で効かなかったことも正直に。画像だけ・動画だけのノイズポストはテキストが無いのでミュートワードでは1ミリも減りません。ここはアカウント単位ミュート(API側)を併用するしかない。あと、ミュートワードは73個を超えたあたりから「シグナルの取りこぼし」が増えました。具体的には無料をミュートしたら無料の技術カンファレンス告知まで消えた。月1回は登録ワードを棚卸しして、攻めすぎたワードを削る作業が必須です。完全放置は無理でした。

タイムラインを情報インフラとして使うなら、こうした自動化を支える学習自体への投資も効きます。私はPython自動化とクラウドの体系はUdemyの実装系講座(A8.net経由)と、bot常駐用にConoHa VPS(A8.net)で組みました。手元PCを24時間つけっぱなしにするより、月額数百円のVPSに逃がした方が電気代込みで安く、GitHub Actionsの無料枠を超えた時の退避先にもなります。

まとめると、Xのキーワードミュート自動化は「APIが無い」という一点で多くの人が諦めますが、Playwright+Claudeのハイブリッドなら今日から動きます。まずはcollect.pyをローカルで1回回して、Claudeが返すミュート候補を眺めるところから始めてみてください。


🛠 関連リンク(筆者の制作物)

本記事のような Claude / GitHub Actions を使った開発の自動化を、すぐ自分の環境で動かしたい方へ:

※自社商品・サイトへのリンク(プロモーションを含みます)。

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?