文章声明
本文章中所有内容仅供学习交流,严禁用于商业用途和非法用途,否则由此产生的一切后果均与文章作者无关,若有侵权,请联系我立即删除!
概要
- 记录一下B站 protobuf 的解析
- 该篇文章是基于弹幕接口的分析
- 用到的工具 360浏览器 notepad++
- 这个东西很久之前我就遇到过,奈何当初不懂,也是网上找的解决方案,所以现在回过头来继续研究
逆向目标
解析出弹幕的信息, 查看字段的映射表
开始整活
抓包
打开F12 选择XHR请求 定位到搜索数据包, 选择url过滤 seg
分析
这是个什么东西?
- 要说乱码,他有中文,要说数据正常,他也让人看不懂
- 请求数据都是正常的,为什么响应看不懂
- 其实就是一个
Protocol Buffer
类型的 - 官方网址: https://protobuf.dev/getting-started/
什么是Protocol Buffer
?
-
这篇文章不详细讲,因为东西太多了…
-
看看AI的回答
Protocol Buffer (Protobuf) 是一种跨平台语言中立的数据格式,用于序列化结构化数据。它由 Google 开发,用于在其分布式系统中进行高效的数据交换。 Protobuf 的特点: 高效: Protobuf 是二进制编码的,比 JSON 或 XML 等文本格式更紧凑和高效。这可以显著减少带宽使用和处理时间。 语言无关: Protobuf 定义语言无关,这意味着可以使用任何支持的编程语言生成和解析 Protobuf 消息。 可扩展: Protobuf 支持向现有消息类型添加新字段,而不会破坏向后兼容性。 灵活: Protobuf 消息可以表示各种数据结构,包括嵌套消息、枚举和重复字段。 Protobuf 的工作原理: 定义消息类型: 使用 Protobuf 定义语言(.proto 文件)定义消息类型,其中指定字段名称、类型和规则。 生成代码: 使用 Protobuf 编译器为目标语言(如 C++、Java、Python)生成代码。生成的代码提供用于序列化和反序列化 Protobuf 消息的方法。 序列化数据: 将数据对象序列化为二进制 Protobuf 消息。 传输数据: 通过网络或其他通信信道传输序列化后的消息。 反序列化数据: 在接收端,使用生成的代码将二进制消息反序列化回数据对象。 Protobuf 的优点: 性能高: 与其他数据格式相比,Protobuf 具有更高的性能和更小的消息大小。 跨平台: Protobuf 支持多种编程语言,使其可用于各种平台和应用程序。 可扩展: Protobuf 可以轻松扩展以添加新字段,而不会影响向后兼容性。 广泛使用: Protobuf 被广泛用于 Google 的内部系统以及许多其他公司和项目中。 Protobuf 的应用: RPC 通信: 在分布式系统中进行远程过程调用 (RPC)。 数据存储: 存储和检索结构化数据,例如数据库和缓存。 数据交换: 在不同系统和应用程序之间交换数据,例如 API 和微服务。 配置管理: 存储和管理应用程序和系统配置。
-
总结: 就是一种数据结构,可以跨平台使用,占用空间小
响应数据定位及解析
- 在控制台输出整个函数可以看到每一条数据的结构都是一致的
-
可以看到返回的数据正是我们需要的弹幕数据
-
既然
JS
可以解析,那么python
也同样可以解析 -
定位到
js
解析B站protoc文件
结构时的代码,看看刚开始加载的时候是根据哪些字段加载的,这样我们后期才能通过Python
进行还原 -
任选其中一个字段按照这种格式搜索
"dmid":
-
找到如下这种格式的直接复制即可
-
放到notepad++里解析下,然后定位到和弹幕字段相关的位置处
-
把之前复制的数据放到一个文本文件
json.txt
中 -
编写python代码
with open('./json.txt', encoding='utf-8') as file: d = jsonpath(json.loads(file.read()), '$.nested.bilibili.nested.community.nested.service.nested.dm.nested.v1.nested.DanmakuElem') for k, v in d[0]['fields'].items(): print(f"optional {v['type']} {k} = {v['id']};")
-
建立
test.proto
文件
-
生成py文件
protoc ./test.proto --python_out=.
解析测试
import test_pb2
response = requests.get('https://api.bilibili.com/x/v2/dm/web/history/seg.so', params=params, cookies=cookies, headers=headers)
byte_str = response.content
person2 = test_pb2.Person()
person2.ParseFromString(byte_str)
print(person2) # 就可以得到明文弹幕数据了