mcpField
X
x-article-publisher

x-article-publisher

github.com/mavscuiマーケティング・グロース19362 回インストール33 週間前に更新
リポジトリ

x-article-publisher について

Markdown 記事を X Articles 用の書式付き下書きにする Claude 向けスキルです。Python スクリプトでタイトル、HTML、画像位置を抽出し、ブラウザー自動化とクリップボードで入力します。公開は手動です。

主な機能

  1. 01Markdown を構造化データに変換
  2. 02本文を書式付き HTML に変換
  3. 03HTML と画像をクリップボードにコピー
  4. 04ブロックインデックスで画像を配置
  5. 05自動公開せず下書きを保存

活用シーン

  1. 01X Articles 向け Markdown 記事の準備
  2. 02見出し、リンク、リスト、太字の書式維持
  3. 03記事本文内の複数画像の配置
  4. 04手動公開前の下書き確認

MCP 対応

ブラウザーを自動操作して X Articles を開き編集するため、Playwright MCP が必要です。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mavscui/agent-skills-hunter --skill x-article-publisher

インストール後、Claude Code で/x-article-publisherを入力して読み込まれたか確認します。

詳細

X 記事パブリッシャー

Markdown コンテンツを X(Twitter)の記事エディターに公開します。リッチテキスト変換により書式を保持します。

前提条件

  • ブラウザー自動化用の Playwright MCP
  • Premium Plus サブスクリプションで X にログインしていること
  • 依存関係をインストールした Python 3.9 以降:pip install Pillow pyobjc-framework-Cocoa

スクリプト

~/.claude/skills/x-article-publisher/scripts/ にあります:

parse_markdown.py

Markdown を解析して構造化データを抽出します:

python parse_markdown.py <markdown_file> [--output json|html] [--html-only]

title、cover_image、content_images(位置指定用の block_index を含む)、html、total_blocks を含む JSON を返します。

copy_to_clipboard.py

画像または HTML をシステムのクリップボードにコピーします:

# Copy image (with optional compression)
python copy_to_clipboard.py image /path/to/image.jpg [--quality 80]

# Copy HTML for rich text paste
python copy_to_clipboard.py html --file /path/to/content.html

ワークフロー

方針:「先にテキスト、後から画像」

画像を複数含む記事では、最初にテキストコンテンツをすべて貼り付けてから、block_index を使って正しい位置に画像を挿入します。

  1. Python スクリプトで Markdown を解析 → title、block_index 付きの画像、HTML を取得
  2. X の記事エディターに移動
  3. カバー画像(最初の画像)をアップロード
  4. タイトルを入力
  5. HTML をクリップボードにコピー(Python) → Cmd+V で貼り付け
  6. block_index で指定された位置にコンテンツ画像を挿入
  7. 下書きとして保存(自動公開は絶対に行わない)

効率的な実行の原則

目標:操作間の待ち時間を最小限に抑え、スムーズな自動化を実現します。

1. 不要な browser_snapshot を避ける

ほとんどのブラウザー操作(click、type、press_key など)は、返却結果にページの状態を含みます。各操作の後に個別に browser_snapshot を呼び出す必要はありません。操作の返却結果に含まれるページの状態をそのまま使ってください。

❌ 错误做法:
browser_click → browser_snapshot → 分析 → browser_click → browser_snapshot → ...

✅ 正确做法:
browser_click → 从返回结果中获取页面状态 → browser_click → ...
2. 不要な browser_wait_for を避ける

browser_wait_for は次の場合にのみ使用してください:

  • 画像のアップロード完了を待つ場合(textGone="正在上传媒体")
  • ページの初期読み込みを待つ場合(まれなケース)

ボタンや入力欄が表示されるのを待つために browser_wait_for を使用しないでください。ページの読み込みが完了すれば、すぐに使用できます。

3. 独立した操作を並行して実行する

2 つの操作に依存関係がない場合は、同じメッセージ内で複数のツールを並行して呼び出せます:

✅ 可以并行:
- 填写标题 (browser_type) + 复制HTML到剪贴板 (Bash)
- 解析Markdown生成JSON + 生成HTML文件

❌ 不能并行(有依赖):
- 必须先点击create才能上传封面图
- 必须先粘贴内容才能插入图片
4. ブラウザー操作を連続して実行する

各ブラウザー操作が返すページの状態には、必要な要素参照がすべて含まれています。それらの参照をそのまま次の操作に使用してください:

# 理想流程(每步直接执行,不额外等待):
browser_navigate → 从返回状态找create按钮 → browser_click(create)
→ 从返回状态找上传按钮 → browser_click(上传) → browser_file_upload
→ 从返回状态找应用按钮 → browser_click(应用)
→ 从返回状态找标题框 → browser_type(标题)
→ 点击编辑器 → browser_press_key(Meta+v)
→ ...
5. 準備を事前に済ませる

ブラウザー操作を始める前に、すべての準備を済ませてください:

  1. Markdown を解析して JSON データを取得する
  2. HTML ファイルを /tmp/ に生成する
  3. title、cover_image、content_images などの情報を記録する

これにより、ブラウザー操作の段階では、途中で停止してデータを処理することなく連続して実行できます。

ステップ 1:Markdown を解析する(Python)

parse_markdown.py を使って、すべての構造化データを抽出します:

python ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md

JSON 出力:

{
  "title": "Article Title",
  "cover_image": "/path/to/first-image.jpg",
  "content_images": [
    {"path": "/path/to/img2.jpg", "block_index": 5, "after_text": "context for debugging..."},
    {"path": "/path/to/img3.jpg", "block_index": 12, "after_text": "another context..."}
  ],
  "html": "<p>Content...</p><h2>Section</h2>...",
  "total_blocks": 45
}

主なフィールド:

  • block_index:このインデックス(0 始まり)のブロック要素の後に画像を挿入します
  • total_blocks:HTML 内のブロック要素の合計数
  • after_text:参照/デバッグ用にのみ保持され、位置指定には使用しません

クリップボード用に HTML を一時ファイルに保存します:

python parse_markdown.py article.md --html-only > /tmp/article_html.html

ステップ 2:X の記事エディターを開く

browser_navigate: https://x.com/compose/articles

重要:ページの読み込み後に表示されるのは下書き一覧であり、エディターではありません。次の手順が必要です:

  1. ページの読み込み完了を待つ:browser_snapshot を使ってページの状態を確認します
  2. すぐに「create」ボタンをクリックする:「添加标题」などのエディター要素を待たないでください。これらは create をクリックした後にのみ表示されます
  3. エディターの読み込みを待つ:create をクリックした後、エディター要素が表示されるまで待ちます
# 1. 导航到页面
browser_navigate: https://x.com/compose/articles

# 2. 获取页面快照,找到 create 按钮
browser_snapshot

# 3. 点击 create 按钮(通常 ref 类似 "create" 或带有 create 标签)
browser_click: element="create button", ref=<create_button_ref>

# 4. 现在编辑器应该打开了,可以继续上传封面图等操作

注意:browser_wait_for text="添加标题" をページの読み込み待ちに使用しないでください。このテキストは create をクリックした後にのみ表示されるため、タイムアウトします。

ログインが必要な場合は、手動でログインするようユーザーに促してください。

ステップ 3:カバー画像をアップロードする

  1. 「添加照片或视频」ボタンをクリックします
  2. カバー画像のパス(JSON 出力から取得)を指定して browser_file_upload を使用します
  3. 画像がアップロードされたことを確認します

ステップ 4:タイトルを入力する

  • プレースホルダーが「添加标题」のテキストボックスを探します
  • browser_type を使ってタイトル(JSON 出力から取得)を入力します

ステップ 5:テキストコンテンツを貼り付ける(Python クリップボード)

Python を使って HTML をシステムのクリップボードにコピーし、貼り付けます:

# Copy HTML to clipboard
python ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py html --file /tmp/article_html.html

次に、ブラウザーで:

browser_click on editor textbox
browser_press_key: Meta+v

これにより、すべてのリッチテキスト書式(H2、太字、リンク、リスト)が保持されます。

ステップ 6:コンテンツ画像を挿入する(block_index による位置指定)

重要な改善点:テキストとの一致に頼らず、block_index を使って正確な位置を指定します。

位置指定の原理

HTML を貼り付けた後、エディター内のコンテンツは、段落、見出し、引用などのブロック要素の連なりになります。各画像の block_index は、第 N ブロック要素の後に挿入することを示します。

操作手順
  1. すべてのブロック要素を取得する:browser_snapshot でエディターのコンテンツを取得し、テキストボックスの下にあるすべての子要素を探します
  2. インデックスで位置を指定する:block_index に基づいて該当するブロック要素をクリックします
  3. 画像を貼り付ける:画像をクリップボードにコピーしてから貼り付けます

各コンテンツ画像(content_images 配列から)について:

# 1. Copy image to clipboard (with compression)
python ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py image /path/to/img.jpg --quality 85
# 2. Click the block element at block_index
# Example: if block_index=5, click the 6th block element (0-indexed)
browser_click on the element at position block_index in the editor

# 3. Paste image
browser_press_key: Meta+v

# 4. Wait for upload (use short time, returns immediately when done)
browser_wait_for textGone="正在上传媒体" time=2
位置指定の方法

browser_snapshot が返す構造では、エディターのコンテンツは通常、次のようになっています:

textbox [ref=xxx]:
  generic [ref=block0]:  # block_index 0
    - paragraph content
  heading [ref=block1]:   # block_index 1
    - h2 content
  generic [ref=block2]:  # block_index 2
    - paragraph content
  ...

block_index=5 の後に画像を挿入するには:

  1. エディターのテキストボックスの下にある 6 番目の子要素を探します(インデックスは 0 から始まります)
  2. その要素をクリックします
  3. 画像を貼り付けます

注意:画像を 1 枚挿入するたびに、それ以降の画像の実際の位置がずれます。先に挿入した画像が後続画像のインデックスに影響しないよう、block_index の大きい順に画像を挿入することをおすすめします。

逆順で挿入する例

画像が 3 枚あり、block_index がそれぞれ 5、12、27 の場合:

  1. block_index=27 の画像を先に挿入します
  2. 次に block_index=12 の画像を挿入します
  3. 最後に block_index=5 の画像を挿入します

こうすることで、画像を挿入するたびに、すでに位置を指定した前の画像の位置に影響しません。

ステップ 7:下書きを保存する

  1. コンテンツが貼り付けられたことを確認します(単語数の表示を確認します)。
  2. 下書きは自動保存されます。必要に応じて「保存」ボタンをクリックします。
  3. 「预览」をクリックして書式を確認します。
  4. 次のように報告します:「下書きを保存しました。確認して手動で公開してください。」

重要なルール

  1. 絶対に公開しない — 下書きの保存のみ行います
  2. 最初の画像をカバー画像にする — 最初の画像をカバー画像としてアップロードします
  3. リッチテキストへの変換 — 貼り付ける前に、必ず Markdown を HTML に変換します
  4. クリップボード API を使用する — 適切な書式を保つため、クリップボード経由で貼り付けます
  5. ブロックインデックスで位置を指定する — 画像を正確に配置するため、block_index を使用します
  6. 逆順で挿入する — block_index の大きい順に画像を挿入します
  7. H1 タイトルの扱い — H1 はタイトルとしてのみ使用し、本文には含めません

対応する書式

  • H2 見出し(## )
  • 引用(> )
  • コードブロック(...)— X は <pre><code> に対応していないため、引用に変換されます
  • 太字(**)
  • ハイパーリンク(text)
  • 番号付きリスト(1. 2. 3.)
  • 箇条書き(- )
  • 段落

実行例

ユーザー:「/path/to/article.md を X に公開して」

# Step 1: Parse Markdown
python ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md > /tmp/article.json
python ~/.claude/skills/x-article-publisher/scripts/parse_markdown.py /path/to/article.md --html-only > /tmp/article_html.html
  1. https://x.com/compose/articles に移動します
  2. カバー画像をアップロードします(カバー画像には browser_file_upload のみを使用します)
  3. タイトルを入力します(JSON の title から取得します)
  4. HTML をコピーして貼り付けます:
    python ~/.claude/skills/x-article-publisher/scripts/copy_to_clipboard.py html --file /tmp/article_html.html
    
    次に、browser_press_key Meta+v を実行します
  5. コンテンツ画像ごとに、block_index の逆順で次の操作を行います:
    python copy_to_clipboard.py image /path/to/img.jpg --quality 85
    
    • block_index の位置にあるブロック要素をクリックします
    • browser_press_key Meta+v を実行します
    • アップロードが完了するまで待ちます
  6. プレビューで確認します
  7. 「下書きを保存しました。確認して手動で公開してください。」

ベストプラクティス

なぜ文字列の照合ではなく block_index を使うのですか?
  1. 正確な位置指定:文字列の内容に依存せず、似た文字列が複数箇所にあっても正しく位置を特定できます
  2. 信頼性:インデックスは決定的であり、文字列が似ているために混同することはありません
  3. デバッグが容易:after_text は手動確認用として引き続き使用できます
なぜブラウザー内の JavaScript ではなく Python を使うのですか?
  1. ローカルでの処理がより信頼できます:Python は OS のクリップボードを直接操作でき、ブラウザーのサンドボックスによる制限を受けません
  2. 画像の圧縮:アップロード前に画像を圧縮する(--quality 85)ことで、アップロード時間を短縮します
  3. コードの再利用:スクリプトは固定されているため、変換ロジックを毎回書き直す必要がありません
  4. デバッグが容易:スクリプトを単独でテストでき、問題の特定も容易です
待機の戦略

重要なポイント:browser_wait_for の textGone パラメーターは、文字列が消えるとすぐに戻ります。time は最大待機時間であり、固定の待機時間ではありません。

  • ❌ 余裕を持たせた待機:time=5 または time=10。アップロードに2秒しかかからない場合、残りの時間が無駄になります
  • ✅ 短い間隔でのポーリング:time=2。条件を満たすとすぐに戻り、最大でも2秒待ちます
# 正确用法:短 time 值,条件满足立即返回
browser_wait_for textGone="正在上传媒体" time=2

# 错误用法:固定长时间等待
browser_wait_for time=5  # 无条件等待5秒,浪费时间

原則:「どれくらい待つ必要があるか」をあらかじめ決めるのではなく、妥当な最大値を設定して、条件をできるだけ早く検出できるようにします。

画像挿入の効率化

画像ごとのブラウザー操作を5ステップから2ステップに減らします:

  • 旧:クリック → メディアを追加 → メディア → 写真を追加 → file_upload
  • 新:段落をクリック → Meta+v
カバー画像とコンテンツ画像
  • カバー画像:専用のアップロードボタンがあるため、browser_file_upload を使用します
  • コンテンツ画像:Python のクリップボードから貼り付けます(より効率的です)

コメント