疑问:请问如何解压 B 站弹幕文件?

2019-07-15 08:16:43 +08:00
 evenIfAlsoGo

这个问题困扰了两三天,目前一步一步分析出来应该是解压的问题。请问此文件到底是什么解压方式?该如何通过工具解压?

文件示例: https://api.bilibili.com/x/v1/dm/list.so?oid=71163662

部分 Header:

Content-Encoding: deflate

Content-Type: text/xml

Transfer-Encoding: chunked

Accept-Encoding: gzip, deflate, br

最初:采用 Aria2 下载时,已添加 --http-accept-gzip,但依旧报错,incorrect header check

Exception: [AbstractCommand.cc:350] errorCode=1 URI=https://api.bilibili.com/x/v1/dm/list.so?oid=71163662 -> [GZipDecodingStreamFilter.cc:110] errorCode=1 libz::inflate() failed. cause:incorrect header check

已尝试的方法:

① curl -O url --compressed,成功解压,文件正常显示!唯一成功的途径。

② bandzip 为文件损坏,gzip 为 not in gzip format

③ fs.readFile('1.gz', function(err, data){ console.log(data) })

Buffer 94 bd 5b 73 5c 49 72 26 f8 57 30 78 18 d3 8c 38 47 e1 11 ee 1e 11 36 25 68 6a ba 5b 9a b5 51 4b 6d dd db 3b ad 7d 59 4b 24 12 dd 1c 75 b1 ca ea 22 55 ...

④ node.js:Gunzip/Inflate, Error: incorrect header check

const fs = require('fs'), zlib = require('zlib') fs.createReadStream('./1.gz').pipe(zlib.createGunzip()).pipe(fs.createWriteStream('1.xml')) console.log("文件解压完成。")

希望大家可以帮忙看看,感激不尽!

4927 次点击
所在节点    程序员
34 条回复
evenIfAlsoGo
2019-07-15 10:11:48 +08:00
@zsdroid 哈哈,其实用 JS 的 XMLHttpRequest 也可以直接获取到内容(手动滑稽)
evenIfAlsoGo
2019-07-15 10:14:14 +08:00
@lzvezr 因为我是导出所有下载链接的 URL,然后采用工具批量创建对应文件夹、重命名和下载的。具体你可以看看这个: https://github.com/evgo2017/bilibili_video_download
evenIfAlsoGo
2019-07-15 10:15:20 +08:00
lzvezr
2019-07-15 10:57:12 +08:00
@evenIfAlsoGo 但是你说的这些 nodejs 都能做到啊
evenIfAlsoGo
2019-07-15 11:14:29 +08:00
@lzvezr 是的,只是大部分用户应该不会直接使用 node.js ,所以需要选择适合的方案和下载工具(后续添加浏览器直接下载),考虑到用户体验就需要做的更多一些。
jinliming2
2019-07-15 12:05:04 +08:00
curl -I -XGET https://api.bilibili.com/x/v1/dm/li st.so?oid=71163662
HTTP/1.1 200 OK
Date: Mon, 15 Jul 2019 04:01:06 GMT
Content-Type: text/xml
Transfer-Encoding: chunked
Connection: keep-alive
Bili-Trace-Id: 3c3183c3895d2bfa:3c3183c3895d2bfa:0:0
Content-Encoding: deflate
Last-Modified: Mon, 15 Jul 2019 12:02:12 GMT
X-Cache-Webcdn: BYPASS from cds-uswest-webcdn-v6-01

由此可知,他们不是用 gzip 压缩的,而是 deflate,你用 gunzip 解压当然失败!
jinliming2
2019-07-15 12:11:53 +08:00
curl -I -XGET [ V 站禁止外链???] -H "Accept-Encoding: gzip"
HTTP/1.1 200 OK
Date: Mon, 15 Jul 2019 04:06:30 GMT
Content-Type: text/xml
Transfer-Encoding: chunked
Connection: keep-alive
Bili-Trace-Id: d9c73fea75d2bfc:d9c73fea75d2bfc:0:0
Content-Encoding: deflate
Last-Modified: Mon, 15 Jul 2019 12:07:36 GMT
X-Cache-Webcdn: BYPASS from cds-uswest-webcdn-v6-01

由此可知,他们会忽略你给的 Accept-Encoding 头,固执的继续使用 deflate 压缩。
shansing
2019-07-15 12:34:21 +08:00
@jinliming2 我也注意到 Content-Encoding 是 deflate 了。但是这个能说是服务端忽略了 Accept-Encoding 头吗?因为 Accept-Encoding 中也包含了 deflate,所以也是没问题的吧。倒是优先级,不知道有没有问题,但肯定不是在前面的优先级高,因为 br 更高级,服务端实现一般会优先返回 brotli 压缩的内容,而它却是写在 Accept-Encoding 最后的。
Paladinfeng
2019-07-15 12:47:13 +08:00
你可以去 Github 搜一个项目叫 bilibili-api

/**
* 弹幕文件解析器.
* 弹幕文件(list.so)有三个部分
* 第一个部分为一个 Int, 表示第二部分的长度
* 第二部分为一个 Json, 标识各个弹幕的等级(用于屏蔽设置)
* 第三部分为一个 gzip 压缩过的 xml
*
* Web 端的弹幕是一个明文 xml, 与 APP 的接口是不一样的.
*
* json 部分形如 {"dmflags":[{"dmid":12551893546958848,"flag":10}],"rec_flag":1,"rec_text":"开启后,全站视频将按等级等优化弹幕","rec_switch":1}
* xml 部分形如 <d p="12509048833835076,0,117373,5,25,16777215,1551001292,0,d2c5fc5">硬核劈柴</d>
*
* @see com.hiczp.bilibili.api.danmaku.DanmakuAPI.list
*/
evenIfAlsoGo
2019-07-15 13:08:06 +08:00
@jinliming2
@shansing 我采用 curl --http1.0 想去掉 chunked 看看是否是这个原因,是不成功的,依旧是 HTTP/1.1
evenIfAlsoGo
2019-07-15 13:11:03 +08:00
@Paladinfeng 好的,谢谢!
shansing
2019-07-15 13:20:51 +08:00
@evenIfAlsoGo 我尝试请求 Accept-Encoding 不包含 deflate 甚至要求不压缩都不成功,可能服务端放弃这些向下兼容的东西了。
evenIfAlsoGo
2019-07-15 17:27:38 +08:00
@shansing 谢谢!
jinliming2
2019-07-16 01:21:28 +08:00
@shansing #28 看我的第二个回复,里面我指定了 Accept-Encoding 为 gzip 了,不包含 deflate,但服务器依旧以 deflate 进行回复,可见服务端是忽略这个头的……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/582958

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX