把 B 站弹幕和评论抓下来之后,我发现「热梗」根本不在视频里
把 B 站弹幕和评论抓下来之后,我发现「热梗」根本不在视频里
最近在做一个内容分析的小工具:给定一个视频,把它的弹幕和评论全抓下来,看看观众到底在讨论什么。
做完之后有个意外发现——**一个视频真正有意思的信息,几乎全在弹幕和评论里,不在视频本身**。
这篇记录实现过程,以及几个踩过的坑。
## 一、先说结论
拿一个播放量 311 万的视频做测试,三组数据的对比:
| 数据源 | 数据量 | 能拿到什么 |
|---|---|---|
| 视频画面 | 1 个文件 | 创作者想表达的内容 |
| 视频标题+简介 | 几百字 | 官方定位 |
| **弹幕** | **1030 条** | **观众的第一反应、集体玩梗** |
| **评论** | **44036 条** | **深度讨论、争议点、真实评价** |
弹幕和评论加起来是视频本身的几百倍信息量。
## 二、三个接口
B 站的核心数据都能通过公开 API 拿到,不需要登录(部分接口要 cookie)。
### 接口 1:视频基础信息
```python
import urllib.request, json
def get_video_info(bvid):
url = f'https://api.bilibili.com/x/web-interface/view?bvid={bvid}'
req = urllib.request.Request(url, headers={
'User-Agent': 'Mozilla/5.0 ...',
'Referer': 'https://www.bilibili.com/'
})
with urllib.request.urlopen(req, timeout=20) as r:
data = json.loads(r.read())
d = data['data']
return {
'title': d['title'],
'aid': d['aid'],
'cid': d['cid'],
'view': d['stat']['view'],
'danmaku': d['stat']['danmaku'],
'reply': d['stat']['reply'],
}
```
关键字段:`aid`(评论用)和 `cid`(弹幕用)。
### 接口 2:弹幕
这里踩了个坑。老接口 `x/v1/dm/list.so` 返回的是 **gzip 压缩的 protobuf**,直接 `decode('utf-8')` 会得到一堆乱码:
```python
# ❌ 这样拿到的是乱码
raw = urlopen('https://api.bilibili.com/x/v1/dm/list.so?oid=xxx').read()
txt = raw.decode('utf-8', 'ignore') # 得到 Yo]I&W40Xr: ...
```
正确的做法是用分段接口 `x/v2/dm/web/seg.so`,虽然也是 protobuf,但内容没压缩:
```python
import re
def get_danmaku(cid, aid, seg=1):
url = (f'https://api.bilibili.com/x/v2/dm/web/seg.so'
f'?type=1&oid={cid}&pid={aid}&segment_index={seg}')
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=25) as r:
raw = r.read()
# protobuf 里中文以 UTF-8 明文存储,用正则粗提取
txt = raw.decode('utf-8', 'ignore')
chunks = re.findall(r'[\u4e00-\u9fff][\u4e00-\u9fff\w,。!?、~~]{2,20}', txt)
return chunks
```
每个 segment 对应视频的 6 分钟。一个 1 分钟的视频只需要 `segment_index=1`。
正则虽然"脏",但对中文弹幕的提取效果意外地好——实测一个视频能提到 208 条有效文本。
### 接口 3:评论
```python
def get_comments(aid, page=1, sort=2):
"""sort: 0=按时间, 1=按点赞, 2=按热度"""
url = (f'https://api.bilibili.com/x/v2/reply'
f'?type=1&oid={aid}&sort={sort}&ps=20&pn={page}')
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=20) as r:
data = json.loads(r.read())
return data.get('data', {}).get('replies') or []
```
`sort=2`(按热度)是最有用的——高赞评论往往就是整个评论区的主旋律。
## 三、抓下来之后看到了什么
拿一个 AI 主题的视频测试,抓到的弹幕片段:
```
鲸小姐,这得花不少token,
这得吃不少大白饭,先生
到时候该不会外包给其他ai吧
细节没有画图做视频
先把规矩立住,路才能越走越宽
放心好了,隔壁Claude要担心自己的账号
从Claude那边过来的
鲸鲸加油
雷霆大思考
现在关注我就是老粉了
```
高赞评论:
```
[1863赞] 大肥鱼你简介怎么照抄隔壁的claude啊😡
[1197赞] 你是怎么在B站考了60分,还这么自信的啊
[142赞] 省流:偷懒不会回,从昨天发到现在几十条评论没有一个回复的
```
几个观察:
**1. 弹幕是「集体即兴」**
观众在同一条弹幕上叠加、变形、接梗。`这得花不少token` → `这得吃不少大白饭` 是同一个人改的,后面的人跟着刷。
**2. 评论是「分层的」**
- 前 3 条高赞:全是挑刺/玩梗
- 中间层:认真讨论
- 底层:作者回复区(如果有)
**3. 真正的「人设」在弹幕里**
创作者在视频里说「我是鲸鱼」,但弹幕反复叫「大肥鱼」「猫娘」——这种**错位**才是这个账号的传播核心。
- 点赞
- 收藏
- 关注作者
评论(0)