Bilibili直播弹幕抓取(3):弹幕传输协议分析
前言
有了前两篇的铺垫,其实到这里再去分析基本就没有什么难点了,无非是苦力活罢了。
所以这篇文章主要是总结如何更好的分(偷)析(懒)。
抓包分析
弹幕消息
这里挑选了一个比较典型的包,它包括了弹幕内容并且有多条弹幕。
可以很明显看出,它是由两条弹幕构成的:
其中选中的文本部分显然是一个JSON,前面的非 ASCII 码没猜错应该就是头部了,我们看一下第一条弹幕的头部。
1 | 00 00 01 0F 00 10 00 00 00 00 00 05 00 00 00 00 |
首先头部的长度是 16,也就是 0x10,所以大胆猜测其中的 00 10 字段就是头部长度,结合后面第二条弹幕头部的相同字段的值,基本确定就是头部长度。
那么可以猜测前面 00 00 01 0F 也就是 0x10F (别忘了 TCP 是大端序),应该是这条弹幕帧(头部+JSON文本数据)的长度。
观察到偏移 0X10F 处开始正好是第二条弹幕的内容,而且第二条弹幕头部中这个字段的值是 0x125,两者相加是 0x234 即整个包的长度,所以确定猜测是正确的。
此外还有一个非零值是 0x5,暂时猜测不出来它的意思,先放放。
也就是说目前头部分析出来的结果是:
1 | | 00 00 01 0F | 00 10 | 00 00 00 00 00 05 00 00 00 00 |
然后我们再把注意力放到后面的 JSON 数据上,这里切换到 Fiddler 的 JSON 视图:
由于头部部分不是 UTF-8 编码干扰了解码,所以 Fiddler 只解析出来了第一条弹幕的文本部分,不过已经足够了。
其中有一个很重要的字段是 cmd,显然是 command 的缩写,它的值是 DANMU_MSG,所以显然是“弹幕消息”的意思。实际上通过抓包还可以看到有 WISH_BOTTLE, SEND_GIFT 等值,因此可以确定 cmd 用来指明弹幕的种类。
同时可以看到 info 中直接就包含了弹幕的内容(“看不懂”)、弹幕发送者的 id (“266649406”)、弹幕发送者的昵称(“简短回忆”)和头衔(“靖菌”)等等内容。
到这里弹幕的内容我们就可以抓取到了,但是还有一些细节性的东西。
人气值
持续抓包一段时间后,我们可以看到有非常多这样长度固定并且一来一回的包。
分别查看内容如下:
可以看到上行包长度固定是 16,下行包固定长度是 20,它们头部字段的含义跟之前的分析吻合,同时在下行的包中可以发现其中四字节的字段 0x73E8 就是人气值。
另外刚才弹幕包中头部为 0x5 的字段这里变成了 0x2 和 0x3,因此猜测应该是消息种类。
这里头部最后一个字段出现了一个 0x1,暂时不知道什么意思,先放着。
握手
现在我们回过头来分析最开始的握手包。
首先是请求包。
可以看到跟之前的分析都是吻合的,而且这里消息种类是 0x7 代表客户端请求连接,同时后面的文本信息包含了用户 id(这里我是游客,所以是0)、房间 id、客户端类型和客户端版本等信息。
然后是返回的包。
这个包很简单,只要头部,并且其中消息种类 0x8 表示服务器接受连接。
总结
可以看出,抓取弹幕的核心是要正确解析头部中的消息种类,目前出现过的种类有:
- 0x2 客户端请求人气值
- 0x3 服务端返回人气值
- 0x5 弹幕消息、礼物等等
- 0x7 客户端请求连接
- 0x8 服务端允许连接
以及头部的结构:
1 | | 帧长度(4) | 头部长度(2) | 未知1(2) | 消息种类(4) | 未知(4) | |
虽然还有很多未知的字段,不过按照目前掌握的内容已经足以正常抓取弹幕了。
站在巨人的肩膀上
decorator.js
抓包总是有限制的,当然我们也可以选择分析前端的代码,不过我当时看到 .min
就放弃了:
不过 Chrome 格式化之后搜索 DANMU_MSG 后还是有点收获的:
可以看到之前 cmd 的其它取值。
但是分析这个文件是真的难受,我看了 30min 就放弃了,不知道有没有好的分析办法。
Bilibili HTML5 Live
后来我偶然发现了这个脚本:Bilibili HTML5 Live
它包含了之前我抓包分析的内容,还有一些我没有分析到的内容,总之看这份代码基本上就可以偷懒了(逃
比如之前提到的消息种类判定代码:
1 | function onMessage(evt) { |
此外可以看到之前的“未知1”字段是版本号,“未知2”字段可能是序列编号?这里存疑,不过不影响抓取弹幕。
小结
Bilibili 弹幕抓取系列到这里就结束了,这个过程中虽然绕了很多弯路浪费了大把时间,不过我还是学到了不少知识:
- WebSocket
- FiddlerScript 编写
- WireShark 基本使用
- 抓包分析能力(二进制敏感度?)
另外感觉计网光过了一遍课本真的不够,用起来总是觉得力不从心,等什么时候闲下来就去做计网实验吧(挖坑)。