怎么按关键词搜 Reddit 帖子并收集评论
先用 Reddit 帖子搜索找帖子,再对留下的帖子调 Reddit 帖子评论。下面的示例一共 8 次调用,花费 $0.02;失败的调用不扣费。
更新于
要做的事:Reddit 上经常有人问“该买哪个”,下面的回答又长又实在。你想把某个产品或话题下的这些回答变成数据。先搜帖子,留下讨论最多的几个,再连同回复关系一起读出评论。最后得到一个 CSV,每行一条评论,带所属帖子、社区、内容、得分、作者,如果是回复,还带它回复的是哪条评论。
不需要 Reddit 账号,不用注册应用,也不用 OAuth token。每次调用就是带着 key 发一个 HTTPS 请求。
分步操作
第一步:搜帖子
调用Reddit 帖子搜索,query 填关键词。决定返回内容的是这两个参数:
sort:relevance(默认,相关度)、latest(最新)或popular(得分最高)。published_within:day、week、month或year,分别是最近一天、一周、一个月、一年。不传就是不限时间。
一次调用返回约 25 个帖子,每次 $0.004。每个帖子有 id(Reddit 的 t3_ 格式,比如 t3_1p4kx9q)、url、type(text、image 或 video)、title、正文 text(链接帖和图片帖为空)、published_at、author.username、得分 metrics.likes 和评论数 metrics.comments。加上 view=full 还有 ext.subreddit(所在社区,格式为 r/名称)、ext.upvote_ratio(赞同比例)、ext.link(链接帖指向的外部链接)、ext.flair 和 ext.nsfw。
curl -G "https://api.okdata.online/v1/reddit/posts/search" \
-H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'query=air fryer' \
-d sort=popular -d published_within=month -d view=full
要下一页,就把 page.next_cursor 原样作为 cursor 传回去;page.has_more 为 false 时停下。
第二步:读评论
把帖子的 id(带不带 t3_ 都行)或链接 url 传给Reddit 帖子评论。sort 可选 best(默认,Reddit 自己的排序)、latest(最新)或 popular(得分最高)。
一次调用返回约 10 条评论,每次 $0.002,同时带上它们下面的前几层回复。每条评论有 id(t1_ 格式)、post_id、parent_id、text、author.username、得分 likes、回复数 replies 和 published_at。一级评论的 parent_id 为 null;回复的 parent_id 是它所回复评论的 t1_ ID,靠它就能把整个讨论还原成一棵树。
curl -G "https://api.okdata.online/v1/reddit/posts/comments/list" \
-H "Authorization: Bearer $OKDATA_API_KEY" \
-d id=t3_1p4kx9q -d sort=popular
翻页方式和第一步一样,用 page.next_cursor。每多一页,就多一批一级评论和它们下面的前几层回复。
第三步:用 Python 串起来
import csv
import os
import requests
API = "https://api.okdata.online"
HEADERS = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
SEARCH_PAGES = 2
THREADS = 6 # 每个帖子读第一页评论;每个帖子一次调用
def get(path, **params):
body = requests.get(API + path, headers=HEADERS, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']} (charged: {body['charged']})")
return body
posts, cursor = [], None
for _ in range(SEARCH_PAGES):
body = get("/v1/reddit/posts/search", query="air fryer", sort="popular", published_within="month", view="full", **({"cursor": cursor} if cursor else {}))
posts += body["data"]["items"]
if not body["page"]["has_more"]:
break
cursor = body["page"]["next_cursor"]
busiest = sorted(posts, key=lambda p: p["metrics"]["comments"] or 0, reverse=True)[:THREADS]
with open("reddit_comments.csv", "w", newline="", encoding="utf-8") as f:
out = csv.writer(f)
out.writerow(["community", "post_id", "post_title", "comment_id", "parent_id", "author", "score", "replies", "published_at", "text"])
for p in busiest:
for c in get("/v1/reddit/posts/comments/list", id=p["id"], sort="popular")["data"]["items"]:
out.writerow([p["ext"]["subreddit"], p["id"], p["title"], c["id"], c["parent_id"], c["author"]["username"], c["likes"], c["replies"], c["published_at"], c["text"]])
parent_id 为空的行是一级评论,其余是回复。想读更深的讨论,就对最关键的那几个帖子继续翻评论页。
注意事项
- 是得分,不是点赞。 Reddit 显示的是得分(赞成票减反对票),
metrics.likes和评论的likes存的就是它。得分接近零,可能是有争议,不一定是没人看。 - 哪些字段是空的。 Reddit 不显示浏览量,
metrics.views为 null。评论者的头像、粉丝数和属地都不返回;回复数不确定时replies为 null。 - 删除的内容。 已删除的帖子返回
not_found,不收钱。被删的评论可能仍然留在讨论里,正文被 Reddit 换成占位符,分析之前先过滤掉。 - 搜索覆盖面。 返回的是 Reddit 自己的搜索对这个查询和时间段给出的结果,不是所有提到这些词的帖子。想看全,就多换几种说法搜。
- 官方渠道。 Reddit 有自己的 Data API。它的 Data API 条款规定,商业用途,或者超出速率限制的研究用途,都需要和 Reddit 另签协议。个人项目或在限制以内、经过批准的研究,用官方 API 就挺好。
- 重试不会重复扣费。 每次调用带一个
Idempotency-Key请求头;24 小时内同样的请求配同样的 key,会拿回存好的结果,不再扣费。
各平台评论的成本对比,见采集 1000 条评论要花多少钱。把这类讨论整理成结论的做法,在口碑与评论分析里。
示例花费
搜两页过去一个月得分最高的空气炸锅(air fryer)帖子,再取评论最多的 6 个帖子各自的第一页评论
| 接口 | 调用次数 | 单价 | 小计 |
|---|---|---|---|
| Reddit 帖子搜索 | 2 | $0.004 | $0.008 |
| Reddit 帖子评论 | 6 | $0.002 | $0.012 |
| 合计 | 8 | $0.02 |
按本页生成时的价格计算。失败的调用不扣费。
在你的 AI 里用(MCP)
先接好 MCP 服务,然后直接说你要什么。智能体会自己找到这些接口、看清价格,再用你的余额调用。
可以这样说在 Reddit 搜过去一个月的 air fryer 帖子,按得分从高到低,取两页。挑评论最多的 6 个帖子,每个按得分读第一页评论,整理成一张表:社区、帖子标题、评论内容、得分、是不是回复。再总结大家推荐什么、后悔买了什么。
智能体第一次调用 call 工具时发送的内容
{
"endpoint": "reddit.posts.search",
"params": {
"query": "saturn rings"
},
"idempotency_key": "<新的 UUID>"
}