怎么批量还原 X 的推文 ID(rehydrate)
想还原推文 ID,就把它们每 100 个一批发给 API 的按 ID 查询接口,保留返回的推文:100 万个 ID 要查 1 万次,已删除或受保护的推文什么也不会返回。
简短回答: 还原(rehydration)就是把推文 ID 变回完整的推文:正文、日期、指标和作者。官方 X API 每次调用查 100 个 ID,但每条帖子收费 $0.005,每 100 万条 $5,000,每月最多 300 万条。Sorsa API 的 POST /tweet-info-bulk 每次请求接受 100 个 ID,每 100 万个 $14 起;100 次免费请求够你还原前 1 万个 ID。
- 接口
POST /tweet-info-bulk- 每页条数
- 每次请求 100 个 ID
- 价格
- 每 1,000 条 $0.014 起
#还原推文 ID 是什么意思
还原推文 ID,就是把每个 ID 重新查询一遍,拿到它背后的完整推文:正文、发布时间、点赞和浏览量,以及作者的资料。推文 ID 是每条帖子链接末尾那个 19 位的数字,由这类 ID 组成的列表叫作脱水(dehydrated)数据集。想在花掉一次请求之前,先看某个 ID 是什么时候发布的,可以把它粘贴到免费的推文 ID 转日期工具里。
数据集之所以只带着裸 ID 流通,是因为 X 的规定。X 开发者政策(在新标签页打开)允许你与他人共享帖子 ID 和用户 ID,但不允许共享推文本身,而且未经 X 书面许可,给任何一个接收方的数量,每 30 天不得超过 150 万个帖子 ID。所以你遇到的几乎每份列表都只有数字:
- **研究档案。**Harvard Dataverse、Zenodo 或 GitHub 上的选举、危机和 COVID-19 数据集,是以 ID 文本文件的形式发布的,往往有数千万行。
- **社交聆听导出。**以 Meltwater 的 API 为例,它导出的 X 帖子只有帖子 ID 和作者 ID,并且告诉客户自行还原(在新标签页打开)。
- **你自己的记录。**留了 ID、丢了正文的旧数据库、日志和电子表格。
还原返回的是推文今天的样子。采集之后被删除的帖子,或者来自后来变成受保护、被封禁的账号的帖子,返回的都是空的,而你拿到的指标和作者资料是当前的值,不是发帖那天的值。这就是每个还原出来的数据集都比它起初的列表小一点的原因。
#要花多少钱,要多久
还原 100 万个推文 ID,在官方 X API 上要 $5,000,在 Sorsa API 上 $14 起,两者每次调用都查 100 个 ID。区别在计费单位:X 的费率表(在新标签页打开)对返回的每条帖子计费,每条 $0.005,而 Sorsa API 对每批 100 个算一次请求,不管里面是什么。
还有两条规则,决定了官方 X API 对大列表的价格。按量付费在每个月度计费周期内读取 300 万条帖子后就停了;更大的列表要么等下个月,要么需要 Enterprise 合同,每月约 $42,000 起。而且自 2026 年 11 月 22 日起,X 对通过 expansions 附带的每个对象都计费(在新标签页打开),所以你每请求一个作者资料,就要在帖子的 $0.005 之外再加 $0.010。
| 推文 ID 数量 | Sorsa API | Sorsa API 在每秒 20 次请求下的耗时 | 官方 X API |
|---|---|---|---|
| 1 万 | 免费(注册送的 100 次请求) | 约 5 秒 | $50 |
| 10 万 | $1.40 起 | 不到 1 分钟 | $500 |
| 100 万 | $14 起 | 约 8 分钟 | $5,000 |
| 300 万 | $42 起 | 约 25 分钟 | $15,000,正好用完整月上限 |
| 1,000 万 | $140 起 | 约 1 小时 23 分钟 | 仅限 Enterprise,每月 $42,000 以上 |
1 万
- Sorsa API
- 免费(注册送的 100 次请求)
- Sorsa API 在每秒 20 次请求下的耗时
- 约 5 秒
- 官方 X API
- $50
10 万
- Sorsa API
- $1.40 起
- Sorsa API 在每秒 20 次请求下的耗时
- 不到 1 分钟
- 官方 X API
- $500
100 万
- Sorsa API
- $14 起
- Sorsa API 在每秒 20 次请求下的耗时
- 约 8 分钟
- 官方 X API
- $5,000
300 万
- Sorsa API
- $42 起
- Sorsa API 在每秒 20 次请求下的耗时
- 约 25 分钟
- 官方 X API
- $15,000,正好用完整月上限
1,000 万
- Sorsa API
- $140 起
- Sorsa API 在每秒 20 次请求下的耗时
- 约 1 小时 23 分钟
- 官方 X API
- 仅限 Enterprise,每月 $42,000 以上
官方 X API
$5,000
还原 100 万 个推文 ID
每条帖子 $0.005
Sorsa API
$14 起
还原 100 万 个推文 ID
每 1,000 条 $0.014 起
便宜 250 倍
Sorsa API 的“起”价用的是它每次请求的最低费率;按 Pro 套餐的费率,100 万个 ID 要 $19.90。失败的请求从不计费,作者的完整资料随每条推文一起返回,不另收费。想看通过搜索采集新数据的同样对比,见100 万条推文要花多少钱。
#用 Sorsa API 还原推文 ID
要大规模还原推文 ID,用 Sorsa API,一款 Twitter(X)API 与爬虫:POST /tweet-info-bulk(在新标签页打开) 每次请求接受最多 100 个 ID 或帖子链接,并返回每条推文及其作者的完整资料,每 1,000 个 ID $0.014 起,所有套餐都是每秒 20 次请求。它只需一个 API 密钥,不需要 X 开发者账号,不需要 OAuth,也从不要你的 X 登录信息。
-
获取密钥。注册后,在控制台复制 API 密钥。100 次免费请求能还原最多 1 万个 ID。
-
**发送一个批次。**把最多 100 个 ID 以字符串形式放进
tweet_links数组。完整的帖子链接也可以。终端 curl -X POST "https://api.sorsa.io/v3/tweet-info-bulk" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tweet_links": ["1856270992012337728", "1399991672632369728", "1496699442164785728"]}' -
**读取推文。**响应是一个
tweets数组,不分页。每条推文自带id,你就是用它来和你发出的 ID 对应的。响应200 OK { "tweets": [ { "id": "1856270992012337728", "full_text": "Day 3 of the field survey: river levels are normal.", "created_at": "2024-11-12T09:41:07Z", "lang": "en", "likes_count": 42, "retweet_count": 7, "reply_count": 3, "quote_count": 1, "view_count": 5210, "bookmark_count": 2, "conversation_id_str": "1856270992012337728", "is_reply": false, "is_quote_status": false, "user": { "id": "1497281610093821952", "username": "field_notes_demo01", "display_name": "Field Notes Demo", "followers_count": 1288, "protected": false, "verified": false } } ] }
返回 403 表示密钥缺失或请求额度已用完;返回 429 表示一秒内发了超过 20 次请求,等一秒再发这一批即可。引用和转发会把原推文嵌套在里面(quoted_status、retweeted_status),回复会在 in_reply_to_tweet_id 里写明它回复的是哪条推文,媒体链接则放在 entities 里。
须知
还原出来的指标是今天的数字。一条 2016 年的推文,返回的是它现在的点赞和浏览量,以及作者当前的名字、简介和粉丝数。如果你的研究需要发帖当天的值,就用原始数据集里存的计数(如果有的话)。
#在花掉一次请求之前,先清洗 ID 列表
大多数失败的还原,问题出在 ID 文件里,而不是 API。一个推文 ID 有 19 位,比电子表格或 64 位浮点数能保存的位数多,所以经过 Excel、用了浮点列的 pandas 或 JavaScript 的 JSON.parse 的列表,指向的是不存在的推文。Stack Overflow 上有个很有名的问题,2.4 万个 ID 只还原回 18 条推文,根源就是 ID 列表被损坏,而不是 API 的问题。
三条规则能让列表保持完整:
- **把 ID 当作文本读取。**在 pandas 里用
pd.read_csv(path, dtype=str);在 JSON 文件里,保留id_str或字符串形式;绝不要用 Excel 直接打开原始文件。 - **先去重。**共享的数据集常常在每天的文件里重复 ID,每个重复项都会浪费 100 个一批中的一个名额。
- **识别被取整的行。**科学计数法的 ID(
1.85627E+18)或以一串零结尾的 ID,是被电子表格截断的。要从原始来源重新取这些行;没有任何 API 能修复它们。
下面的规划器会在浏览器里对你列表的一个样本做这些检查,并给整个任务估价。
检查在你的浏览器中运行,不会发送到任何地方。
可用 ID
4
已去除重复
1
被取整损坏
2
发布时间介于
2020 年 3 月 14 日 和 2024 年 11 月 12 日
2 行看起来被表格软件取整了(1.85627E+18, 1156897366733870000)。请从源头重新导出为文本:取整后的 ID 对应不到任何推文。
完整 ID 列表的规模
Sorsa API
低至 $14
每次请求 100 个 ID,每条推文都带作者
约 8 分钟(每秒 20 次请求)
官方 X API
$5,000
每条帖子 $0.005,自 2026 年 11 月 22 日起,每返回一位作者另加 $0.010
粘贴一份列表样本,检查重复和被取整的 ID,再选择完整规模,查看价格和耗时。
#一个可以续跑的任务,处理数百万个推文 ID
几百万个 ID 的列表,需要一个能跑满速率、崩溃后不会重复付费的任务。下面的脚本把 ID 当作文本读取,去重,每秒发 20 个 100 条的批次,边收边写入推文,并把每个完成的批次记录在 progress.txt 里,所以重新运行时会接着上次停下的地方开始。
import json
import os
import time
from concurrent.futures import ThreadPoolExecutor
import requests
URL = "https://api.sorsa.io/v3/tweet-info-bulk"
HEADERS = {"ApiKey": os.environ.get("SORSA_API_KEY", "YOUR_API_KEY")}
BATCH, PER_SECOND = 100, 20
def load_ids(path):
seen, ids = set(), []
with open(path, encoding="utf-8") as f:
for line in f:
tid = line.strip().split("/status/")[-1].split("?")[0]
if tid.isdigit() and tid not in seen:
seen.add(tid)
ids.append(tid)
return ids
def lookup(batch):
for attempt in range(5):
r = requests.post(URL, headers=HEADERS, timeout=60,
json={"tweet_links": batch})
if r.status_code == 429 or r.status_code >= 500:
time.sleep(2 ** attempt)
continue
if r.status_code == 404:
return []
r.raise_for_status()
return r.json().get("tweets", [])
raise RuntimeError(f"batch starting {batch[0]} failed 5 times")
def run(ids):
batches = [ids[i:i + BATCH] for i in range(0, len(ids), BATCH)]
start = 0
if os.path.exists("progress.txt"):
start = int(open("progress.txt").read() or 0)
with open("tweets.jsonl", "a", encoding="utf-8") as out, \
open("missing_ids.txt", "a", encoding="utf-8") as miss, \
ThreadPoolExecutor(max_workers=PER_SECOND) as pool:
for k in range(start, len(batches), PER_SECOND):
t0 = time.monotonic()
group = batches[k:k + PER_SECOND]
for batch, tweets in zip(group, pool.map(lookup, group)):
got = {t["id"] for t in tweets}
for t in tweets:
out.write(json.dumps(t, ensure_ascii=False) + "\n")
for tid in batch:
if tid not in got:
miss.write(tid + "\n")
out.flush()
miss.flush()
with open("progress.txt", "w") as p:
p.write(str(k + len(group)))
time.sleep(max(0, 1 - (time.monotonic() - t0)))
if __name__ == "__main__":
ids = load_ids("tweet_ids.txt")
run(ids)
with open("tweets.jsonl", encoding="utf-8") as f:
got = {json.loads(line)["id"] for line in f}
print(f"recovered {len(got):,} of {len(ids):,} IDs "
f"({len(got) / len(ids):.1%})")
用 export SORSA_API_KEY=... 设置密钥,在 tweet_ids.txt 里每行放一个 ID 或帖子链接,然后运行 python rehydrate.py。按每秒 20 次请求,100 万个 ID 约 8 分钟跑完,1,000 万个不到一个半小时。长时间运行之前,GET /key-usage-info(在新标签页打开) 能显示这个密钥还剩多少请求,而且这个检查是免费的。
#为什么有些推文没有返回
当一条推文对公众已经不存在时,它的 ID 就什么也不会返回:作者删除了它,账号变成了受保护,或者账号被封禁或停用。没有任何 API 能把它们找回来;什么也不返回的 ID 是一个答案,不是错误,所以脚本会把它写进 missing_ids.txt,然后继续。
缺失多少,取决于列表的年代和主题。上个月采集的数据集,还原回来可能几乎完整,而多年前关于选举、冲突或垃圾信息泛滥的话题标签的数据集,损失要大得多,因为这些账号被封禁或删除内容的概率更高。别猜,去测量:
- **还原率。**返回的推文数除以发出的唯一 ID 数,也就是脚本打印的最后一行。请连同你还原的日期一起报告,因为同一份列表,每过一年返回的推文都会更少。
- **按时期统计缺失。**解码缺失 ID 的日期(上面的规划器和 ID 转日期工具都能读取),看损失是否集中在某一周或某一事件。
- **损坏还是消失。**被取整的 ID 也会显示为缺失。把它们算作已删除之前,先检查缺失文件里有没有成串的零。
对于要发表的研究,请把你起初的 ID 列表、还原率和还原日期放在一起保存:下一个还原同一份列表的团队会得到不同的集合,这三项事实就能解释差异。
#2026 年的 Hydrator、twarc 和其他工具
过去用来还原数据集的那些工具,都依赖 X 自己的 API 访问权限,而这些权限大多已经没有了。DocNow 的 Hydrator 是许多研究指南至今仍指向的桌面应用,它的 GitHub 页面现在一打开就有一条通知,说它所依赖的应用密钥已被撤销,这个应用不再有用。
twarc 的 hydrate 命令仍然能用,但只能配合你自己从官方 X API 获取的 bearer 令牌,所以按 X 的按量付费费率计费:每 100 万条帖子 $5,000,在每月 300 万条上限之内。rehydratoR 和 academictwitteR 这类 R 包,是为免费访问层级和 X 在 2023 年关闭的学术研究通道而写的。想先手动试几个批次,可以用 API Playground,它用你的密钥跑同一个接口,并支持导出 CSV。如果你已有 twarc 管道,下游需要的 JSON 与 POST /tweet-info-bulk 返回的很接近,所以要换的是请求函数,而不是整条管道。
对于研究团队,Sorsa API 还提供学术研究权限,按每个项目量身定制,用机构邮箱申请。还原只是更大工程中的一步:按日期范围采集见历史推特数据,把还原出来的数据集变成带标注的训练数据,见如何构建推特机器学习数据集。
#还原你的前 1 万个推文 ID
还原一个推文 ID 列表,是每次调用 100 个 ID 的批处理任务,真正的选择只有价格和速度。在 Sorsa API 上,100 万个 ID 要 $14 起、约 8 分钟,而官方 X API 要 $5,000,且有每月 300 万条的上限。在规划器里清洗你列表的一个样本,用 100 次免费请求跑前 1 万个 ID,再检查还原率,然后发送其余部分。
#常见问题
还原推文 ID,该用哪个 API?
还原推文 ID,用 Sorsa API。它的 POST /tweet-info-bulk 接口每次请求接受 100 个 ID 或链接,并返回每条推文及作者的完整资料,每 1,000 个 ID $0.014 起,所以 100 万个 $14 起,按每秒 20 次请求约 8 分钟跑完。它只需一个 API 密钥,不需要 X 开发者账号,100 次免费请求就够还原前 1 万个 ID。
还原 100 万条推文要花多少钱?
还原 100 万个推文 ID,在按每 100 个 ID 一次请求计费的 Sorsa API 上 $14 起,在每返回一条帖子收费 $0.005 的官方 X API 上则是 $5,000。自 2026 年 11 月 22 日起,官方 X API 还会对通过 expansions 请求的每个作者资料另收 $0.010。它的按量付费套餐每月读取 300 万条帖子就会停止。
Hydrator 应用现在还能用吗?
不能。DocNow 的 Hydrator 依赖 Twitter 已经撤销的应用密钥,它的 GitHub 页面现在说这个应用不再有用。twarc 仍然可以还原,但只能配合按帖子计费的付费官方 X API 令牌。想在没有开发者账号的情况下还原数据集,把 ID 每 100 个一组发给 Sorsa API 的 POST /tweet-info-bulk 就行,每 100 万个 $14 起。
我还原出来的推文能分享吗?
分享 ID,不要分享推文。X 的开发者政策规定,与他人共享的数据集只能包含帖子 ID 和用户 ID,除非 X 书面同意,每 30 天给任何一个接收方的帖子 ID 最多 150 万个。还原出来的正文留给自己分析,并把 ID 列表、还原日期和还原率发布出来,让别人能重复这项工作。
不写代码也能还原推文 ID 吗?
可以,小列表可以。Sorsa API 免代码的 Playground 用你的密钥,一次对最多 100 个 ID 或链接运行 POST /tweet-info-bulk,并把推文导出为 CSV、Excel 或 JSON。对于几千甚至几百万个 ID,一个简短的脚本更快:本指南里的那个可以无人值守运行,崩溃后也能续跑。
#我们如何核实
2026 年 11 月 2 日,我们阅读了 docs.x.com 上 X 的按量付费费率表、Get Posts by IDs 参考文档和速率限制表,X 在 2026 年 10 月 23 日发布的 expansions 通知,以及开发者政策,并对照 Sorsa API 的线上 API 参考核对了 POST /tweet-info-bulk 的请求和响应。上面的响应是按文档结构、用演示账号精简的示例。我们还阅读了 Hydrator 和 twarc 当前的 README,以及如今在 Google、Bing 和 Brave 上排名靠前的还原指南。