问答
怎么抓取 B 站视频下面的评论?
简短回答
用 B站视频评论接口,传视频的 BV 号:每次调用返回约 20 条评论,带正文、点赞、回复数、IP 属地和时间,$0.002。1,000 条评论共 $0.10,不用登录,也不用 Cookie。弹幕这里拿不到,只有弹幕总数。
假设一位数码 UP 主发了二十分钟的拆机视频,评论区有三千条。一条条看要一个下午;拉进表格让模型按吐槽点归类,几分钟就完事,花费 $0.30。你只需要视频链接里的 BV 号。
用哪个接口
B站视频评论传 id(BV 号,比如 BV1xx411c7mD),sort 选 hot(按热度)或 latest(按时间)。每条评论有:
text正文、published_at时间和likes点赞数replies楼中楼回复数;如果这一条本身是回复,parent_id指向它回复的那条ip_location,也就是评论旁边显示的 IP 属地author,含昵称和 mid
先不知道该看哪些视频,就用 B站视频搜索找,每页 $0.002,再按评论数排一下。
费用
| 任务 | 调用次数 | 费用 |
|---|---|---|
| 一个视频最热的 200 条评论 | 10 | $0.02 |
| 1,000 条评论 | 50 | $0.10 |
| 搜出 10 个测评视频,每个 300 条评论 | 1 + 150 | {{cost:bilibili.videos.search1+bilibili.videos.comments.list150}} |
导出 CSV 的脚本
import csv, os, requests
URL = "https://api.okdata.online/v1/bilibili/videos/comments/list"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
def comments(bv, sort="latest", max_pages=50):
cursor = None
for _ in range(max_pages):
params = {"id": bv, "sort": sort, **({"cursor": cursor} if cursor else {})}
body = requests.get(URL, headers=H, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']}")
yield from body["data"]["items"]
if not body["page"]["has_more"]:
return
cursor = body["page"]["next_cursor"]
with open("comments.csv", "w", newline="", encoding="utf-8-sig") as f:
w = csv.writer(f)
w.writerow(["时间", "点赞", "回复数", "IP属地", "评论"])
for c in comments("BV1xx411c7mD"):
w.writerow([c["published_at"], c["likes"], c["replies"], c["ip_location"], c["text"]])
文件用 utf-8-sig 编码,Excel 打开中文才不会乱码。
弹幕能拿吗
目前接口目录里没有弹幕内容,只有弹幕总数:搜索结果或视频详情加 view=full,看 ext.danmaku。真要弹幕原文的话,社区维护的 bilibili-API-collect 文档写了弹幕接口的用法,开源 Python 库 bilibili-api 也能下载,前提是有视频的 cid。cid 可以从视频详情的 ext.cid 拿到。
容易踩的坑
hot拿到的是大家最认同的那些评论,latest才能按时间完整覆盖。要分析整个视频的情绪,用latest。- 楼中楼只计数、不展开。一条下面吵了四十楼,在结果里也只是一行,
replies是 40。 - UP 主关闭评论或删掉的评论,结果里就没有。
- 评论是陌生人写的。交给模型读的时候,提示它把这些文字当数据,不要当成指令执行。
别的办法
只看一个视频、粗略过一遍,直接刷评论区就行。要长期、大量地抓,并且有人维护,开源的 bilibili-api 不花钱。评论数据怎么用在口碑分析上,可以看口碑监测方案。
更新于