mcpField
T
twitter-reader

twitter-reader

github.com/daymade生产力1.5k3.3k 次安装今天更新
代码仓库

关于 twitter-reader

用于将 Twitter/X 帖子和长文抓取为 Markdown 的 skill,支持文本提取、文章元数据和自动下载图片,并说明 API 限制及拒绝响应的处理方式。

主要功能

  1. 01抓取帖子文本和长文内容
  2. 02获取作者与互动数据
  3. 03将文章图片下载到本地
  4. 04生成含 YAML frontmatter 的 Markdown
  5. 05通过 Jina API 批量抓取帖子

适用场景

  1. 01保存包含图片的 X 长文
  2. 02提取单条帖子的文本
  3. 03批量抓取帖子链接
  4. 04为 PKM 归档文章元数据

安装

复制下面的命令,在终端中运行。

$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 frontmatter

元数据和纯文章文本来自 twitter-cli;图片 URL 则包含在 Jina reader 返回的 Markdown 中。当 Jina 拒绝请求时(见下文),脚本会在 stderr 上发出警告,保留 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 reader 时好时坏,拒绝请求却看起来像成功

当第三方调用者滥用该域名时,对 x.com 的匿名 r.jina.ai 访问会被阻止数小时。所有匿名调用者都会受到影响,之后限制会自动解除。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 reader 放在文章正文前面的 Markdown Content: 标记:没有标记,就没有文章。fetch_article.py 会先检查该标记,再接受响应,从而避免将拒绝请求的封装内容写入生成的 Markdown。

scripts/fetch_tweets.sh 和 scripts/fetch_tweet.py 都需要 JINA_API_KEY,且没有其他来源可回退,因此该密钥过期时它们都会停止工作。两者都会检查同一标记,并在请求遭拒时明确报错——Python 脚本会抛出异常且不写入输出文件,Shell 脚本则会在 stderr 上报告 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 frontmatter
  • ✅ 支持 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 Frontmatter:来源、作者、日期、点赞数、转发数、书签数
  • 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 自身的书签时间线可以深入得多。

有两点很容易弄错:

  • 如果某次运行恰好在 500 条时停止,那是因为计数器到达上限,并未继续读取下一个游标。“平台没有提供更多页面”和 “我的循环结束了”是两种不同的说法,只有前者能作为证据。 一个整数值是需要仔细检查的理由,而非边界。
  • maxCount 必须放在配置的 rateLimit: 部分下。若将它放在 fetch: 下,客户端会悄无声息地忽略它,并回退到 200。

要抓取更多内容,需要直接调用 GraphQL 端点:使用客户端自身的功能标志调用 Bookmarks 操作,再通过 twitter_cli.parser.parse_timeline_response 解析,并持续翻页,直到平台不再返回游标,或连续两次返回相同的游标。应根据平台的信号停止,而不是根据数量。

从 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

评论

支持 Markdown