mcpField
T
twitter-reader

twitter-reader

github.com/daymade生産性1.5k3.3k 回インストール今日更新
リポジトリ

twitter-reader について

Twitter/X の投稿や長文記事を Markdown として取得するスキルです。テキスト抽出、記事メタデータの取得、画像の自動ダウンロードに対応し、API の制限や拒否応答の扱いも説明します。

主な機能

  1. 01投稿テキストと記事本文の取得
  2. 02投稿者とエンゲージメント情報の取得
  3. 03記事画像のローカル保存
  4. 04YAML frontmatter 付き Markdown の生成
  5. 05Jina API による投稿の一括取得

活用シーン

  1. 01画像付き X 記事の保存
  2. 02単一投稿のテキスト抽出
  3. 03投稿 URL の一括取得
  4. 04PKM 用の記事メタデータの記録

インストール

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

$npx skills add https://github.com/daymade/claude-code-skills --skill twitter-reader

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

scripts/
fetch_article.py
fetch_tweet.py
fetch_tweets.sh

詳細

Twitter リーダー

メディアを完全にサポートして、Twitter/X の投稿や記事の内容を取得します。

単一の投稿テキストを読む:まず fxtwitter を使用(2026-08-30)

投稿のテキストのみを取得する場合は、fxtwitter のミラー API を優先してください。ログインもキーも不要で、直接利用でき、tweet.text に note_tweet の本文全体が返されます(full_text キーは存在しません。2,324 文字の長文告知も完全な状態で取得できました)。

curl -sS --max-time 20 "https://api.fxtwitter.com/<user>/status/<id>" \
  | python3 -c "import json,sys; t=json.load(sys.stdin)['tweet']; print(t['created_at']); print(t['text'])"

replies は返信数であり、返信スレッドではありません。画像付きの X Articles には、以下の fetch_article.py を使用してください。fxtwitter では記事本文を取得できません。

画像付きの X Articles:fetch_article.py

uv run --with pyyaml python scripts/fetch_article.py <article_url> [output_dir]

例:

uv run --with pyyaml python scripts/fetch_article.py \
  https://x.com/HiTw93/status/2040047268221608281 \
  ./Clippings

このスクリプトは以下を行います。

  • twitter-cli で構造化データ(いいね、リツイート、ブックマーク)を取得します
  • jina.ai API で画像付きのコンテンツを取得します
  • すべての画像を attachments/YYYY-MM-DD-AUTHOR-TITLE/ にダウンロードします
  • 画像参照を埋め込んだ完全な Markdown を生成します
  • メタデータを含む YAML フロントマターを追加します

メタデータと記事のテキストは twitter-cli から取得し、画像 URL は Jina のリーダーが返す Markdown に含まれています。Jina が拒否した場合(以下のセクションを参照)、スクリプトは標準エラー出力に警告を表示し、twitter-cli のテキストを保持して、Images: 0 と報告します。Markdown 自体に問題はなく、画像が含まれないだけです。目に見える画像がある記事で Images: 0 と表示される場合、それは Jina に拒否されたことを示します。

出力例
Fetching: https://x.com/HiTw93/status/2040047268221608281
--------------------------------------------------
Getting metadata...
Title: 你不知道的大模型训练:原理、路径与新实践
Author: Tw93
Likes: 1648

Getting content and images...
Images: 15

Downloading 15 images...
  ✓ 01-image.jpg
  ✓ 02-image.jpg
  ...

✓ Saved: ./Clippings/2026-04-03-文章标题.md
✓ Images: ./Clippings/attachments/2026-04-03-HiTw93-.../ (15 downloaded)

Jina のリーダーは不安定で、拒否されても成功したように見えます

サードパーティの呼び出し元がドメインを悪用すると、匿名の r.jina.ai による x.com へのアクセスは数時間にわたってブロックされます。このブロックはすべての匿名呼び出し元に適用され、その後自動的に解除されます。この2つの状態は、2026-09-12 に数分の間隔で発生しました。

拒否は失敗のようには見えません。curl は終了コード 0 を返し、本文は JSON のラッパーです。

{"data":null,"code":403,"name":"AbuseAlleviationError","status":40305,
 "message":"Anonymous access to domain x.com blocked until <date> ..."}

期限切れまたは残高不足のキーも、"code":402, "name":"InsufficientBalanceError" を含む同じ形式を返します。curl --fail でも、どちらも検出できません。このエンドポイントは、ラッパーを本文に含めたまま HTTP 200 で応答しました。確実な唯一の判定材料は、Jina のリーダーが記事本文の前に付ける Markdown Content: マーカーです。マーカーがなければ記事もありません。fetch_article.py は応答を受け入れる前にこのマーカーを検査するため、拒否を示すラッパーが生成 Markdown に混入するのを防ぎます。

scripts/fetch_tweets.sh と scripts/fetch_tweet.py はどちらも JINA_API_KEY を必要とし、代替ソースがないため、キーの有効期限が切れると動作しなくなります。両方とも同じマーカーを確認し、拒否された場合は明確なエラーを返します。Python 版は出力ファイルを書き込まずに例外を発生させ、シェル版は標準エラー出力に URL を表示して、ゼロ以外の終了コードで終了します。投稿を装ったラッパーを返すことはありません。このリポジトリにはキーは含まれていません。

テキストのみを簡単に取得する場合:

# Single tweet
curl "https://r.jina.ai/https://x.com/USER/status/TWEET_ID" \
  -H "Authorization: Bearer ${JINA_API_KEY}"

# Batch fetching
scripts/fetch_tweets.sh url1 url2 url3

機能

完全な記事モード(fetch_article.py)
  • ✅ 構造化されたメタデータ(投稿者、日付、エンゲージメント指標)
  • ✅ 画像の自動ダウンロード(埋め込みメディアすべて)
  • ✅ ローカル画像参照を含む完全な Markdown
  • ✅ PKM システム向けの YAML フロントマター
  • ✅ X Articles(長文コンテンツ)に対応
シンプルモード(Jina API)
  • テキストのみのコンテンツ
  • 利用可能な状態が不安定(上記のセクションを参照)。どちらのスクリプトも JINA_API_KEY を必要とし、代替手段はありません
  • Jina が応答している間は、テキストをすばやく抽出する用途に使用できます

前提条件

完全な記事モードの場合
  • uv(Python パッケージマネージャー)
  • 追加のセットアップは不要です(twitter-cli は自動でインストールされます)
シンプルモード(Jina)の場合
export JINA_API_KEY="your_api_key_here"
# Get from https://jina.ai/

出力構成

output_dir/
├── YYYY-MM-DD-article-title.md       # Main Markdown file
└── attachments/
    └── YYYY-MM-DD-author-title/
        ├── 01-image.jpg
        ├── 02-image.jpg
        └── ...

返される内容

完全な記事モード
  • YAML フロントマター:ソース、投稿者、日付、いいね、リツイート、ブックマーク
  • Markdown コンテンツ:ローカル画像参照を含む記事全文
  • 添付ファイル:専用フォルダーにダウンロードされたすべての画像
シンプルモード
  • タイトル:投稿者と投稿内容のプレビュー
  • URL ソース:元のツイートへのリンク
  • 公開時刻:GMT のタイムスタンプ
  • Markdown コンテンツ:リモートメディア URL を含むテキスト

対応している URL 形式

  • https://x.com/USER/status/ID(投稿)
  • https://x.com/USER/article/ID(長文記事)
  • https://twitter.com/USER/status/ID(旧形式)

スクリプト

fetch_article.py

画像のダウンロードに対応した高機能な記事取得ツール:

uv run --with pyyaml python scripts/fetch_article.py <url> [output_dir]
fetch_tweet.py

Jina API を使用するシンプルなテキスト専用取得ツール:

python scripts/fetch_tweet.py <tweet_url> [output_file]
fetch_tweets.sh

複数のツイートを一括取得します(Jina API):

scripts/fetch_tweets.sh <url1> <url2> ...

twitter-cli の 500 件上限は、X ではなくツール側の制限です

このスキルは twitter-cli を通じてメタデータを読み取るため、ツール独自の制限が適用されます。 twitter bookmarks やその他のタイムラインコマンドは、設定の内容にかかわらず 500 件で停止します。この上限はクライアント内のモジュール定数です。 twitter_cli/client.py の _ABSOLUTE_MAX_COUNT = 500 が、クライアントの構築時に min(maxCount, 500) として適用されます。どちらの記述もバージョン 0.8.5 から確認したものです。X のブックマークタイムラインは、これよりはるか先まで取得できます。

誤解しやすい点が 2 つあります。

  • ちょうど 500 件で終了した場合、次のカーソルを読み取る段階に到達する前に、独自のカウンターによって処理が停止しています。「プラットフォームが次のページを返さなかった」と「自分のループが終了した」は別の主張であり、証拠となるのは前者だけです。きりのよい数字は、境界ではなく、さらに確認する理由です。
  • maxCount は設定の rateLimit: セクションの下に置く必要があります。fetch: の下に置くと、クライアントは何も通知せずに無視し、既定値の 200 に戻ります。

さらに先まで取得するには、GraphQL エンドポイントを直接呼び出します。クライアント独自の機能フラグを使う Bookmarks オペレーションを実行し、twitter_cli.parser.parse_timeline_response で解析して、プラットフォームがカーソルを返さなくなるか、同じカーソルを 2 回返すまでページングします。件数ではなく、プラットフォームからのシグナルを基準に停止します。

Jina API からの移行

以前のワークフロー:

curl "https://r.jina.ai/https://x.com/..."
# Manual image extraction and download

新しいワークフロー:

uv run --with pyyaml python scripts/fetch_article.py <url>
# Automatic image download, complete Markdown

コメント