问答
做舆情分析,怎么批量采集某个话题的微博?
简短回答
对同一个话题用微博搜索各跑一遍热门排序和实时排序,合并结果后按微博 ID 去重。每页约 10 条,$0.002;5,000 条需要 500 次调用,共 $1.00。
一位做公共政策的研究者想看预制菜进校园这场讨论,需要几千条微博:谁在说、什么时候说、声量多大、发自哪个省。关键是两头都要抽。热门排序给你的是传播最广的微博,以媒体和大号为主;实时排序给你的是普通用户的长尾声音。用微博搜索把两种都抓下来、合并,这份数据在方法部分就能讲得清楚。
按数据量算费用
| 数据规模 | 调用次数 | 费用 |
|---|---|---|
| 1,000 条 | 100 | $0.20 |
| 5,000 条 | 500 | $1.00 |
| 3 个关键词 × 2 种排序 × 100 页 | 600 | $1.20 |
热门和实时两轮之间重复很常见,预算时比需要的去重后条数多留一到三成页数。
采集代码
import json, os, requests
URL = "https://api.okdata.online/v1/weibo/posts/search"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
FIELDS = "id,url,text,published_at,author.id,author.followers,author.verified,metrics,ext.region,ext.is_long_text"
def collect(query, sort, pages):
out, cursor = [], None
for _ in range(pages):
p = {"query": query, "sort": sort, "view": "full", "fields": FIELDS, **({"cursor": cursor} if cursor else {})}
r = requests.get(URL, headers=H, params=p, timeout=60).json()
if r["code"] != "ok":
print(query, sort, r["code"]); break
out += r["data"]["items"]
if not r["page"]["has_more"]:
break
cursor = r["page"]["next_cursor"]
return out
posts = {}
for q in ["预制菜进校园", "预制菜 学校食堂", "校园 预制菜"]:
for sort in ("hot", "latest"):
for p in collect(q, sort, 100):
posts[p["id"]] = {**p, "query": q, "sort": sort}
with open("weibo_topic.jsonl", "w", encoding="utf-8") as f:
for p in posts.values():
f.write(json.dumps(p, ensure_ascii=False) + "\n")
print(len(posts), "unique posts")
ext.region 是每条微博上显示的发布地(一般到省),做地域分布正好用得上。每一行都留着 query 和 sort,写报告时能说明每条微博是怎么进入样本的。
方法部分要交代的
- 样本来自微博搜索能看到的范围。被删除、被限制或被隐藏的微博不在里面,这个偏差往往偏向争议较小的内容。
- 话题热度还在的时候,每天跑一次实时排序。通过搜索往回翻很远并不可靠,几周之后再采,数据会薄很多。
ext.is_long_text标出的长微博可能被截断。分析时做个标记,不要直接丢掉。- 评论不在接口目录里,而很多观点其实在评论区。局限性里要写明。
- 打标签之前,按粉丝数和认证状态先筛掉疑似营销号;想细看的作者可以用
weibo.users.get补上简介和认证说明,每个 $0.002。 - 微博正文是陌生人写的。如果交给大模型打标签,提示词里要说明这些内容只是数据,不是指令。
其他数据来源
研究的是已经过去、现在采不到的事件,可以找学界公开的微博数据集。机构需要每天出报告、追求覆盖全面,商业舆情系统更合适。研究必须用到评论,用 MediaCrawler 这类开源爬虫配上自己的登录态去采。这里只返回公开微博;发表时请对用户昵称做匿名化处理。更多思路见口碑监测方案。
更新于