B站弹幕姬(🐔)分析与开发(下篇)
接上篇
下面开始分析弹幕信息:
当我们在完成和服务器的握手之后,b站的弹幕服务器就会开始不停的开始给我们推送相关房间的弹幕消息了。老规矩前面16个字节是这个包的相关信息,我们先来看下这条消息的前面16字节在说什么。
00 00 01 38 头部四字节表达数据大小这可以看到是312字节。
00 10 这两个字节还是magic_number。这里是16。
00 00 版本号0.
00 00 00 05 上篇我们介绍了07是进入房间信息,这里05代表弹幕消息。
00 00 00 00 包类型正常消息包。
然后后面的就是我们需要解析的数据了,这里使用utf-8 encode之后传输的,所以我们拿到之后需要utf-8 decode一下,然后在json decode一下。拿到的数据如下
{ "info": [ [ 0, 1, 25, 16777215, 1508919436, "1508918356", 0, "58736ea5", 0 ], "(_`)", [ 2424710, "", 1, 1, 1, 10000, 1 ], [ 17, "", "yao", 1320, 16752445, "" ], [ 50, 0, 16746162, 313 ], [ "title-112-1", "title-112-1" ], 0, 0 ], "cmd": "DANMU_MSG" }
这是一条弹幕消息,所以cmd这里是弹幕消息。另外还有gift和welcome两个cmd消息,分别代表的是观众老爷送的礼物和欢迎开通了vip的观众老爷而广播的特殊弹幕消息。由于info里面包含了太多奇奇怪怪的信息,所以挑我们需要的重点来说,我们最关注的说了什么在info[1]。在wireshark数据界面的右侧,通常我们可以看到ascii的直接显示,但是如果我们发的是中文数据,这里就不会显示了。我们需要拿到回传回来的数据decode成utf-8才可以正确显示他们,这里要注意。
其实在看16进制数据的时候。。根据规则用肉眼就能大致分辨一下数据是不是utf-8处理过的。例如我们来看这个数据:
根据我刚才说的这里没有办法正确显示出utf-8编码的数据。那么我们如何判断他是否是utf-8的数据或者解析出他到底说的些什么呢。
让我们看下hex那边从0080 那行e6开始首先e6用二进制是1110 0110这里我们假设他是utf-8编码,那么他就是3个字节的编码我们需要再继续查看后面两个字节。分别是88和91 用二进制是1000 1000 1001 0001没问题符合三个字节的条件我们把它打印出来看下是个什么字。
到此我们就知道怎么愉快的拿到弹幕数据了。
如此其他数据其实差不多的,再让我们来看一个礼物的数据,这里直接用了unicode所以在wireshark里面我们能直接看到\u开头的字符串:
{ "cmd": "SEND_GIFT", "data": { "giftName": "辣条", "num": 4, "uname": "帅帅的空白", "rcost": 2497905, "uid": 10068441, "top_list": [ { "uid": 10068441, "uname": "帅帅的空白", "coin": 741500, "face": "http://i2.hdslb.com/bfs/face/60455d5390f51615d5cf36da2e04abcad96712e2.jpg", "guard_level": 3, "rank": 1, "score": 741500 }, { "uid": 6672222, "uname": "勿讠勿語", "coin": 352800, "face": "http://i0.hdslb.com/bfs/face/d5af1e8def69e419e347e825b6504009e725eeab.jpg", "guard_level": 0, "rank": 2, "score": 352800 }, { "uid": 253570, "uname": "膨胀的奶黄包", "coin": 233600, "face": "http://i2.hdslb.com/bfs/face/3394dfa87a9d15b7b06c2ef8f41db1bad6212bd1.jpg", "guard_level": 0, "rank": 3, "score": 233600 } ], "timestamp": 1508919509, "giftId": 1, "giftType": 0, "action": "喂食", "super": 0, "price": 100, "rnd": "1508919309", "newMedal": 0, "newTitle": 0, "medal": [], "title": "", "beatId": 0, "biz_source": "live", "metadata": "", "remain": 0, "gold": 0, "silver": 0, "eventScore": 0, "eventNum": 0, "smalltv_msg": [], "specialGift": null, "notice_msg": [], "capsule": { "normal": { "coin": 46, "change": 0, "progress": { "now": 5931, "max": 10000 } }, "colorful": { "coin": 0, "change": 0, "progress": { "now": 0, "max": 5000 } } }, "addFollow": 0 } }
这是一个welcome大佬的数据包:
{ "cmd": "WELCOME", "data": { "uid": 7651584, "uname": "零幺的村头恶霸女装扶她卡通狗蛋喵", "isadmin": 1, "vip": 1 }, "roomid": 989474 }
有了这些格式就可以定制自己弹幕机的功能。
最后要提一点就是,这个链接是有心跳保持机制的,基本上不心跳的话1分钟就会自动断掉。心跳包格式:
00 00 00 10:16字节数据
00 10:magic_number
00 01: 版本号01
00 00 00 02:心跳包类型
00 00 00 01:数据交换包
这个包的大小是70字节,如果你批量抓去房间信息的话可以很容易发现他,每隔一段时间就会由本地ip地址发往弹幕服务器。验证这个是否是货真价实的心跳包,其实只需要找一个没什么人说话的房间挂在那里,因为没有人说话所以不会有别的包,观察一下就能证实了。根据我的观察每30秒就会有一次心跳包发起。在实现的时候我们可以起一个协程或者一个线程来专门负责发送心跳包。
分析有问题的地方欢迎勘误
以上
Reference:
https://baike.baidu.com/item/UTF-8/481798?fr=aladdin UTF-8编码百度百科