TODO: 这篇文章是我分析B站直播的数据包的过程,可能会有一些待补充的内容,如果有什么建议可以私信我或者跟评。感谢一下下面的各位做出的卓越贡献~
CREDITS:
冰块TiO2 - 提供样本数据(十个辣条呢~!)
炒鸡嗨客协管徐 - 参考文章:获取bilibili直播弹幕的WebSocket协议(这篇文章写的很全了www)
王远 - 参考文章:b站直播弹幕系统逆向工程笔记 (后来发现这篇文章,参考了这篇文章补全数据包定义。数据包定义写的很详细,可以参考这篇文章~)
我这次分析是通过移动端的h5网页进行的,比如我的直播间是4568796,然后打开的网页是http://live.bilibili.com/h5/4568796,如果被跳转到了一般网页,可以试一下改成iPhone的UA。
主流程(点击前往)
获取房间ID
大部分跟直播间ID是一样的,也就是URL路由后面跟着的那一串数字,比如我的就是4568796,通过API请求房间ID是一样的。
API地址https://api.live.bilibili.com/room/v1/Room/room_init?id=4568796
{
"code": 0,
"msg": "ok",
"message": "ok",
"data": {
"uid": 8759339,
"room_id": 4568796,
"short_id": 0,
"attention": 65,
"online": 15,
"is_portrait": false,
"description": "
主要直播FFXIV,渣渣水平,不要吐槽啊~
\n欢迎大家一起来讨论 一起来玩FF呀 ~
\n偶尔也会直播一些PS4游玩过程~
","live_status": 0,
"area_id": 102,
"parent_area_id": 2,
"parent_area_name": "游戏",
"old_area_id": 3,
"background": "https://static.hdslb.com/live-static/images/bg/6.jpg",
"title": "光之赤石 国际服咸鱼+日常",
"user_cover": "https://i0.hdslb.com/bfs/live/ddc99aeab675f33b0f84afcd41ced570bd9c2d9c.jpg",
"keyframe": "https://i0.hdslb.com/bfs/live/4568796.jpg?12050340",
"is_strict_room": false,
"live_time": "0000-00-00 00:00:00",
"tags": "stormblood,ff14,最终幻想,最终幻想14",
"is_anchor": 1,
"room_silent_type": "",
"room_silent_level": 0,
"room_silent_second": 0,
"area_name": "最终幻想14",
"pendants": "",
"area_pendants": "",
"hot_words": ["2333333", "喂,妖妖零吗", "红红火火恍恍惚惚", "FFFFFFFFFF", "Yooooooo", "啪啪啪啪啪", "666666666", "老司机带带我", "你为什么这么熟练啊", "gg", "prprpr", "向大佬低头", "请大家注意弹幕礼仪哦!", "还有这种操作!", "囍", "打call", "你气不气?", "队友呢?"],
"hot_words_status": 0,
"verify": "",
"new_pendants": {
"frame": null,
"badge": null,
"mobile_frame": null,
"mobile_badge": null
},
"up_session": "",
"pk_status": 0,
"pk_id": 0,
"allow_change_area_time": 0,
"allow_upload_cover_time": 0
}
}
当然也会有不一样的,比如URL后面的数字是419,但是通过API访问拿到的房间ID是3151254。貌似前者在B站的定义是short_id,后者是真实的房间ID,我们请求数据要用的是后面的那个ID。
{
"code": 0,
"msg": "ok",
"message": "ok",
"data": {
"uid": 37164813,
"room_id": 3151254,
"short_id": 419
/*...*/
}
}
JSON 部分感觉有用的字段
FIELD
EXAMPLE
DESCRIPTION
code
0
应该是正常返回代码0,如果出现错误,可能不是这个数值。
data.uid
8759339
UP主用户ID,可以通过https://space.bilibili.com/8759339访问B站空间。
data.room_id
4568796
这是我们要用来连接websocket的ID。
data.short_id
0
如果不是0的话,可以拼接为进入直播间的URL。类似于靓号的存在么?
data.attention
65
粉丝数
data.online
15
旧版的在线人数,现在的人气值。
data.description
HTML
直播间下方的描述,是一段HTML。
data.live_status
0
1表示正在直播,0表示不在直播。
data.description
HTML
直播间下方的描述,是一段HTML。
data.parent_area_name
data.area_name
游戏
最终幻想14
直播的一级分类跟二级分类。
data.live_time
0000-00-00 00:00:00
直播开始的时间,如果全零就是表示不在直播。
data.background
URL
一个URL指向直播间(桌面版)的背景。
data.user_cover
URL
一个URL指向直播间的封面。
data.keyframe
URL
一个URL指向直播间的直播截图。
data.title
光之赤石 国际服咸鱼+日常
直播的标题。
data.tags
stormblood,ff14,最终幻想,最终幻想14
用半角空格分隔的标签列表。
data.verify
UP主认证类型,如果是签约的会有bilibili直播签约主播。
封包结构
封包由头部和数据组成,字节序均为大端模式
头部格式:
偏移量
长度
含义
0
4
封包总大小
4
2
头部长度
6
2
协议版本,目前是1
8
4
操作码(封包类型)
12
4
sequence,可以取常数1
已知的操作码:
操作码
含义
2
客户端发送的心跳包
3
人气值,数据不是JSON,是4字节整数
5
命令,数据中['cmd']表示具体命令
7
认证并加入房间
8
服务器发送的心跳包
示意图:
初始化连接
H5播放器使用的弹幕连接是wss://broadcastlv.chat.bilibili.com/sub,桌面版的会使用CDN的连接,每次都不一样,没有测试过是否每次连接都可用。我使用桌面版的时候就出现过:
wss://tx-live-dmcmt-