问答
推特免费的学术 API 没了,研究者现在怎么采集推文?
简短回答
X 在 2023 年停掉了免费的学术接口。现在研究者可以直接付费给 X(全量历史搜索每条 0.005 美元,2 万条 100 美元),也可以用 X 帖子搜索采集公开帖子,每页约 20 条,$0.006,2 万条共 $6.00。查询按月切分,并把具体检索式写进方法部分。
一位博士生在研究某场政策辩论在 X 上是怎么发酵的,需要 2026 年三个月里的约 2 万条帖子。放在 2023 年以前,学术研究通道能免费给她全量历史搜索。推特在 2023 年 2 月宣布终止这一通道,当年秋天独立技术研究联盟做的调查显示,有 100 多项研究因此被取消、暂停或改变方向。数据现在仍然拿得到,只是要花钱,预算最好像规划实验机时一样提前算好。
两条路线和各自的费用
| 路线 | 2 万条帖子 | 说明 |
|---|---|---|
| X 官方全量历史搜索,按量付费 | 100 美元 | 可回溯到 2006 年,用官方语法,需要 X 开发者账号 |
| 这里的 X 帖子搜索 | $6.00 | 用 X 搜索框语法,每页约 20 条 |
涉及账号层面的分析,可以用 X 账号帖子列表(每页 $0.006)和 X 账号信息(每个账号 $0.001),比如在采集时记录每位作者当时的粉丝数。
按月采集
import json, os, requests
API = "https://api.okdata.online/v1"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
BASE = '("carbon tax" OR #carbontax) lang:en -filter:replies'
MONTHS = [("2026-07-01", "2026-08-01"), ("2026-08-01", "2026-09-01"), ("2026-09-01", "2026-10-01")]
with open("corpus.jsonl", "a", encoding="utf-8") as out:
for since, until in MONTHS:
query, cursor = f"{BASE} since:{since} until:{until}", None
for _ in range(350): # 每月的页数预算
params = {"query": query, "sort": "latest", "view": "full", **({"cursor": cursor} if cursor else {})}
body = requests.get(f"{API}/x/posts/search", headers=H, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']} ({body['request_id']})")
for post in body["data"]["items"]:
out.write(json.dumps({"query": query, "fetched_at": body["meta"]["fetched_at"], **post}, ensure_ascii=False) + "\n")
if not body["page"]["has_more"]:
break
cursor = body["page"]["next_cursor"]
每条记录都带上检索式和 fetched_at,在平台数据不断变化的前提下,尽量让数据集可以复现。
审稿人会问到的方法问题
- 帖子是 X 搜索针对每个查询对公众返回的结果,既不是随机样本,也不是全量,论文里要写明。
- 互动数在采集之后还会变化,要注明采集时间。
- 已删除的帖子和受保护账号不在样本里,研究争议话题时可能带来偏差。
- 公开数据的使用遵守所在机构伦理委员会的要求。论文附带帖子 ID 而不是全文,是比较通行的做法。
其他值得知道的渠道
在欧盟,《数字服务法》第 40 条为通过审核的研究者提供了向平台申请数据的法律途径,适合有机构支持的大型研究。最看重完整性和数据来源时,X 官方全量历史搜索是最干净的选择。有时候已经公开的帖子 ID 数据集就能省掉采集这一步。做多平台研究的话,不少研究者已经转向 Reddit、TikTok 和 YouTube;跨平台采集的做法见趋势研究方案,所有接口的价格见价格页。
更新于