关于 twitter-reader
用于将 Twitter/X 帖子和长文抓取为 Markdown 的 skill,支持文本提取、文章元数据和自动下载图片,并说明 API 限制及拒绝响应的处理方式。
主要功能
- 01抓取帖子文本和长文内容
- 02获取作者与互动数据
- 03将文章图片下载到本地
- 04生成含 YAML frontmatter 的 Markdown
- 05通过 Jina API 批量抓取帖子
适用场景
- 01保存包含图片的 X 长文
- 02提取单条帖子的文本
- 03批量抓取帖子链接
- 04为 PKM 归档文章元数据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ daymade/ claude-code-skills --skill twitter-reader安装后在 Claude Code 中输入/twitter-reader确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
scripts/fetch_article.pyfetch_tweet.pyfetch_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.aiAPI 获取带图片的内容 - 将所有图片下载到
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