Chrome DevTools 可以直接查看二進位類型數據包了!
連接#
通過 Chrome DevTools 可以看到,網頁版 B 站直播的彈幕通過 wss://tx-sh3-live-comet-04.chat.bilibili.com/sub
傳輸,這個地址每次是不一樣的。需要通過 https://api.live.bilibili.com/room/v1/Danmu/getConf?room_id=房間號&platform=pc&player=web
獲得 wss 地址(應該是負載均衡的需要,實際測試連接任意 wss 地址都能正常獲取彈幕)
封包頭部 16 個字節用於標識數據包的長度及類型,數據包格式詳見下表。字節序均為大端模式。參考:https://blog.csdn.net/xfgryujk/article/details/80306776
偏移 | 長度 | 類型 | 含義 |
---|---|---|---|
0 | 4 | int | 數據包長度 |
4 | 2 | int | 數據包頭部長度,固定為 16 |
6 | 2 | int | 數據包協議版本(見下文) |
8 | 4 | int | 數據包類型 (見下文) |
12 | 4 | int | 固定為 1 |
16 | – | byte[] | 數據主體 |
數據包協議版本 | 含義 |
---|---|
0 | 數據包有效負載為未壓縮的 JSON 格式數據 |
1 | 客戶端心跳包,或伺服器心跳回應(帶有人氣值) |
2 | 數據包有效負載為通過 zlib 壓縮後的 JSON 格式數據 |
客戶端建立連接後,需要在 5 秒內發出加入房間(認證)的數據包,否則會被伺服器強制斷開連接。其中有效負載的 key 字段內容可以從之前的 https://api.live.bilibili.com/room/v1/Danmu/getConf?room_id=房間號&platform=pc&player=web
獲取。如發送的認證包格式錯誤,伺服器會立刻強制斷開連接,JSON 字段的詳細說明見下表。
字段 | 類型 | 必選 | 含義 |
---|---|---|---|
uid | number | × | 用戶 UID |
roomid | number | √ | 房間號 |
protover | number | × | 協議版本,目前為 2 |
platform | string | × | 平台,可以是 web |
clientver | string | × | 客戶端版本,可以是 “1.8.5” |
type | number | × | 未知,可以是 2 |
key | string | × | 用戶標識,通過之前提到的接口獲取 |
心跳#
心跳包建議每 30 秒發一次,頭部 16 字節遵守上文規則,負載內容隨意。(b 站通過傳入一個空對象來生成心跳包,然後就有了我之前無法理解的心跳包內容)
通知(彈幕、公告、禮物等)#
有新的彈幕、禮物或其他公告時,伺服器會發送類似下圖的數據包,首先需要使用 zlib.inflate
解壓數據主體部分(除頭部 16 字節外)。解壓後的數據頭部十六字節與原數據頭相同,去除頭部後即為 JSON 格式數據
這裡我們以一個彈幕數據包為例子
可以看到解壓後的數據依然帶有頭部(16 字節),去除頭部後即為 JSON 格式數據,其中的 cmd 字段更為詳細地描述了數據包類型。其中比較明顯的是,['info'][1]
代表彈幕內容, ['info'][2][1]
為發送者,['info'][9]['ts']
為發送時間戳,cmd 的已知格式參考下表
cmd 字段 | 含義 |
---|---|
DANMU_MSG | 收到彈幕 |
SEND_GIFT | 有人送禮 |
WELCOME | 歡迎加入房間 |
WELCOME_GUARD | 歡迎房管加入房間 |
SYS_MSG | 系統消息 |
PREPARING | 主播準備中 |
LIVE | 直播開始 |
下面我展示了幾個常見 cmd 的數據包 JSON 格式,還有很多活動通知 cmd,各位可以自行抓取(如下面的 ACTIVITY_BANNER_UPDATE_V2
就是我寫文章當天出現的活動通知 cmd 類型)
{
"cmd": "SEND_GIFT",
"data": {
"giftName": "辣條",
"num": 5,
"uname": "迪多瑪索",
"face": "http://i2.hdslb.com/bfs/face/1a3b795aafc5887f3f33909c7e66876d23911979.jpg",
"guard_level": 0,
"rcost": 42593386,
"uid": 415822879,
"top_list": [],
"timestamp": 1570368091,
"giftId": 1,
"giftType": 0,
"action": "餵食",
"super": 0,
"super_gift_num": 0,
"price": 100,
"rnd": "EF27025C-4C20-440F-B36F-64CCFABBF68E",
"newMedal": 0,
"newTitle": 0,
"medal": [],
"title": "",
"beatId": "",
"biz_source": "live",
"metadata": "",
"remain": 0,
"gold": 0,
"silver": 0,
"eventScore": 0,
"eventNum": 0,
"smalltv_msg": [],
"specialGift": null,
"notice_msg": [],
"capsule": null,
"addFollow": 0,
"effect_block": 1,
"coin_type": "silver",
"total_coin": 500,
"effect": 0,
"broadcast_id": 0,
"draw": 0,
"crit_prob": 0,
"tag_image": "",
"user_count": 0,
"send_master": null
}
}
{
"cmd": "ACTIVITY_BANNER_UPDATE_V2",
"data": {
"id": 378,
"title": "第6名",
"cover": "",
"background": "https://i0.hdslb.com/bfs/activity-plat/static/20190904/b5e210ef68e55c042f407870de28894b/14vZu7h9pK.png",
"jump_url": "https://live.bilibili.com/p/html/live-app-rankcurrent/index.html?is_live_half_webview=1&hybrid_half_ui=1,5,85p,70p,FFE293,0,30,100,10;2,2,320,100p,FFE293,0,30,100,0;4,2,320,100p,FFE293,0,30,100,0;6,5,65p,60p,FFE293,0,30,100,10;5,5,55p,60p,FFE293,0,30,100,10;3,5,85p,70p,FFE293,0,30,100,10;7,5,65p,60p,FFE293,0,30,100,10;&anchor_uid=22550271&is_new_rank_container=1&area_v2_id=163&area_v2_parent_id=3&rank_type=master_realtime_area_hour&area_hour=1",
"title_color": "#8B5817",
"closeable": 1,
"banner_type": 4,
"weight": 18,
"add_banner": 0
}
}
{
"cmd": "ROOM_REAL_TIME_MESSAGE_UPDATE",
"data": {
"roomid": 101526,
"fans": 294665,
"red_notice": -1
}
}
後記:Chrome 支持直接顯示 WebSocket 二進位包真的能節省很多時間。吹爆 Chrome!