前言
本篇记录下载b站《地下交通站》弹幕的经过,地下交通站在21年初下架,我在20年末发现此番剧已经被隐藏,以防万一保存了弹幕的备份,结果这几天发现居然保存的弹幕文件全是乱码,尝试了几种恢复的方式依旧不行,无奈只能尝试研究b站弹幕的api,看能不能找到历史弹幕的接口尝试保存下来
实时弹幕接口
API接口来自仓库bilibili-API-collect,实时弹幕接口提供了一个proto文件,然而我之前并不太了解proto是什么,浅浅的理解为不是用python语言写的脚本,但是可以编译成python调用,so..
编译proto
仓库内提供了一个在线编译的网站protogen.marcgravell,只需要把proto代码复制然后选择python就可以生成python文件,需要注意的是要把编译后的文件发在一个后缀是*_pb2.py*的文件中才可以调用,我这里直接将其命名为bilibili_pb2.py
调用
仓库内很详细的写了请求方式和请求参数,唯一要说的是segment_index,为1指的是获得前六分钟的弹幕,所以如果我想获取一个时常为48分钟视频的所有弹幕,则要在请求参数里设定segment_index的值从1到8,并将所有的response合在一起,后面的解析方式直接用的仓库作者给的示例:
1 | def getDanmuk(oid, type=1, segment_index=1): |
在return的danmaku 中包含一个elems类,elems中的每个DanmakuElem就包含每个弹幕的各个参数,但如果想用在弹弹play这样的播放器中通常需要使用xml格式的弹幕文件
弹幕xml解析
一条弹幕示例:
1 | <d p="0,1,25,16777215,1312863760,0,eff85771,42759017">前排占位置</d> |
- 弹幕出现的时间,以秒为单位
- 弹幕的模式:1~3 滚动弹幕 4 底端弹幕 5 顶端弹幕 6 逆向弹幕 7 精准定位 8 高级弹幕
- 字号:12 非常小 16 特小 18 小 25 中 36 大 45 很大 64 特别大
- 字体的颜色:将 HTML 六位十六进制颜色转为十进制表示,例如 #FFFFFF 会被存储为 16777215
- Unix 时间戳,以毫秒为单位,基准时间为 1970-1-1 08:00:00
- 弹幕池:0 普通池 1 字幕池 2 特殊池(注:目前特殊池为高级弹幕专用)
- 发送者的 ID,用于「屏蔽此弹幕的发送者」功能
- 弹幕在弹幕数据库中 rowID,用于「历史弹幕」功能
将弹幕存储为xml格式
弹幕接口返回的是这种:
1 | id: 711923911 |
需要注意的是其中ctime返回的是单位为秒的时间戳,progress返回的是单位为毫秒的时间,并且小数位为五位,所以需要转换:
1 | def add_ms(timestamp, ms): |
本来我不了解如何在python中创建一个xml文件,便尝试让copilot帮我写一个出来,不知道是表述的有问题,还是xxx,copilot写出了一个简单粗暴的方法
1 | def store_to_xml(elems, oid): |
可以,很粗暴,不过也能用就是了
除此之外xml还有开头和结尾,干脆也也以这种方式加上去算了
1 | def downloadDanmuk(oid): |
具体也有优化空间,不过我也懒得搞,反正就用一次的脚本,地下交通站有28集,所以调用28次就可以全部下载了
1 | def main(): |
下载后的弹幕很全,平均一集的xml文件大小在1~2m左右
结尾
最后才发现明明已经下架的剧集,居然可以用实时弹幕接口下载,因为在使用之前的利用comment.bilibili.com+oid的方法已经出现404, 不过仓库还提供了一个历史弹幕的接口,方法也差不多,既然已经下载好了,就不再折腾了
最后供上已经下好的弹幕:1
欢迎来到 弹幕保护计划QQ群:495877205
若没有本文 Issue,您可以使用 Comment 模版新建。