问答

做舆情分析,怎么批量采集某个话题的微博?

简短回答

对同一个话题用微博搜索各跑一遍热门排序和实时排序,合并结果后按微博 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 这类开源爬虫配上自己的登录态去采。这里只返回公开微博;发表时请对用户昵称做匿名化处理。更多思路见口碑监测方案。

更新于