拓冰建站拓冰建站
首页 / 资讯中心 / 正文

如何备份B站收藏夹?mybili弹幕下载背后的WBI签名与protobuf解析完全揭秘

如何备份B站收藏夹mybili弹幕下载背后的WBI签名与protobuf解析完全揭秘【免费下载链接】mybili哔哩哔哩收藏夹备份程序 ~ アレ 视频不见了哟项目地址: https://gitcode.com/gh_mirrors/my/mybilimybili是一款开源的哔哩哔哩收藏夹备份程序README.md它能把你的 B 站收藏夹视频、封面、弹幕定时同步到本地 NAS实现视频不见了也有备份的安全感。其中最有技术含量的部分就是它如何绕过 B 站的接口保护用 WBI 签名算法合法请求弹幕接口再把返回的 protobuf 二进制数据手工解析成可读弹幕。本文将带你完整看懂这套逆向实现。 mybili 是什么一句话看懂功能mybili 是一个部署在 NAS 上的后台服务核心能力包括⏰ 定时 5 分钟拉取收藏夹所有视频信息标题、封面、简介 按最高画质自动下载视频到本地全量下载并缓存每个分 P 的弹幕支持在线播放装载 生成 Emby 等媒体库可读的目录结构 订阅 UP 主 / 合集自动发现新视频先看它的 Web 管理界面长什么样进入具体收藏夹后可以看到所有已备份的视频右上角可以切换下载状态下载进度页会展示已缓存视频比例、有效/失效/冻结视频分类统计 为什么需要 WBI 签名B 站为了保护接口不被滥用在 2023 年给一批重要接口包括弹幕接口加上了WBI 签名校验请求 URL 必须携带一个由动态密钥计算出的w_rid参数否则服务端直接拒绝。传统做法是解析 B 站前端混淆 JS 来还原算法。而 mybili 的工程师选择了更硬核的路线——纯 PHP 逆向复现整个签名流程全部逻辑集中在一个文件里app/Services/BilibiliService.php。第 1 步从导航接口偷取动态密钥WBI 密钥不是固定的每次都要实时获取。mybili 请求 B 站网页导航接口/x/web-interface/nav从返回的wbi_img字段中取出两张图片 URLimg_key和sub_keyhttps://i0.hdslb.com/bfs/wbi/xxxxxx.png ← img_key https://i0.hdslb.com/bfs/wbi/yyyyyy.png ← sub_key注意取 key 的技巧BilibiliService.php 第120-121行从 URL 中截取去掉扩展名的文件名作为密钥字符串——图片本身只是幌子真正有用的是文件名。第 2 步固定乱序表混合出 32 位密钥拿到两个 key 后拼接再通过一张写死的 64 位乱序索引表重新洗牌混合表前10位464718253823321550按索引从拼接串中逐个取字符取满 32 位得到mixin_key。这张表是逆向前端代码时挖出来的常量只要 B 站不改混淆逻辑它就永远有效encWbi 函数。第 3 步参数排序 MD5 出 w_rid签名最后一步非常朴素把所有请求参数值中的特殊字符!()*过滤掉按键名字典序排序拼成查询串末尾追加mixin_key整串做MD5→ 得到w_rid参数w_rid md5(排序后的query字符串 32位混合密钥)整个签名只有约 40 行 PHP 代码没有任何外部依赖。这套算法的完整实现见 encWbi()。 弹幕接口按 6 分钟一片分段请求弹幕接口/x/v2/dm/wbi/web/seg.so有两个特点必须带 WBI 签名就是上面破解的那套按时间段分片返回每 6 分钟360 秒一个分段长视频要循环请求多段mybili 的处理方式很聪明getDanmaku 方法$segmentCount ceil($duration / 360); // 视频时长 ÷ 6 分钟 分段数一个 30 分钟的视频会被拆成 5 段依次请求每段都独立签名最后把各段弹幕合并成一个完整数组。更关键的是这个接口不返回 JSON而是返回 protobuf 二进制流。 硬核部分手工解析 protobuf 二进制protobuf 是 Google 的高性能二进制序列化格式一般解析需要引入google/protobuf库并预先生成 PHP 类文件。但 B 站弹幕接口的结构并不公开 proto 定义文件mybili 选择了一条更野的路逐字节手写解析器不依赖任何 protobuf 库。先搞懂 protobuf 的两个基本功① Varint变长整数每个字节只取 7 位有效数据最高位是是否还有下一字节的标记位。小于 128 的数只占 1 字节越大占得越多。② Tag 字节每个字段开头都有一位 tag高 5 位是字段编号低 3 位是线型wire type线型含义读取方式0Varint循环读直到最高位为 0164 位固定长度直接跳过 8 字节2长度前缀字符串/嵌套消息先读 varint 长度再读对应字节532 位固定长度直接跳过 4 字节外层结构找出弹幕数组字段解析器从二进制流第 0 字节开始循环parseDanmakuProtobuf读到字段编号 1且线型 2 → 这就是弹幕条目读出长度后截取该段交给单条弹幕解析器其他字段 → 按上表线型规则直接跳过B 站以后加新字段也不会导致解析崩溃内层结构字段编号对照表单条弹幕的子字段解析在 parseSingleDanmaku逆向还原出的字段表如下字段编号名称线型含义1idvarint弹幕唯一 ID2progressvarint出现时间毫秒3modevarint弹幕模式1-3 滚动 / 4 底部 / 5 顶部4fontsizevarint字号5colorvarint颜色十进制如 16777215 白色6midHashbytes用户哈希脱敏 mid7contentbytes弹幕文本内容8ctimevarint发送时间戳9weightvarint弹幕权重决定优先显示12actionbytes动作类弹幕标记解析结果长这样getDanmaku 中的注释{ progress: 390379, mode: 1, color: 16777215, content: 是我, id: 162000000000000000 }从一坨不可读的二进制字节到结构化弹幕数据全程不到 200 行代码且每个读取点都有边界检查防止越界崩溃——这就是手工逆向的完整闭环。 从二进制到屏幕弹幕的入库与展示解析完只是开始mybili 的弹幕链路还包含三个环节异步下载DownloadDanmakuJob 队列任务驱动 DownloadDanmakuAction用 Redissetnx加锁防止同一分 P 重复下载按分片全量拉取增量入库解析后的弹幕按 1000 条一批插入 SQLite 的 danmaku 表通过弹幕 ID 去重只存新增格式转换Web 端播放时DanmakuConverterService 把 B 站原始字段转成播放器通用格式——毫秒转秒、十进制颜色转#FFFFFF十六进制、高级模式6-9降级为滚动模式高级弹幕还会自动降级提取纯文本前端弹幕播放器通过 /danmaku 接口 获取转换后的数据即可在本地备份的视频上还原出原汁原味的弹幕体验。 相关代码导航模块路径说明WBI 签名 弹幕获取app/Services/BilibiliService.phpgetDanmaku / encWbiprotobuf 解析器app/Services/BilibiliService.phpparseDanmakuProtobuf / parseSingleDanmaku弹幕下载动作app/Services/VideoManager/Actions/Danmaku/DownloadDanmakuAction.php加锁、分片、增量入库弹幕格式转换app/Services/DanmakuConverterService.phpB 站格式 → 播放器格式弹幕表结构database/migrations/2025_06_14_130110_create_danmaku_table.phpSQLite 存储✅ 总结mybili 用一次教科书级的逆向实践证明了没有公开 API 文档 ≠ 数据不可得。WBI 签名导航接口取动态 key → 固定乱序表混合 → 参数排序 MD540 行代码复现 B 站前端混淆逻辑protobuf 解析不装库、不要 proto 文件靠 Varint Tag 两个基本功手写逐字节解析器兼容 B 站后续字段变更对于想学习逆向分析的开发者app/Services/BilibiliService.php 这一个文件就是绝佳的实战教材WBI 签名与 protobuf 二进制解析两大硬核技术都浓缩在其中。【免费下载链接】mybili哔哩哔哩收藏夹备份程序 ~ アレ 视频不见了哟项目地址: https://gitcode.com/gh_mirrors/my/mybili创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门