B站视频、音频下载。油猴脚本

背景

笔者是在b站听歌的(一方面买不起各种会员,一方面有的歌喜欢的是翻唱版本)。所以打算爬取B站的音频(视频偶尔会下架)。

方案

爬取资源,简单来说,就是找到你所需资源的url,然后通过http实现资源的下载。我尝试过多种爬取方案。

python脚本

python脚本爬取,是你能在网上找到的最多的方案,但存在诸多问题:1、每次运行脚本需要手动获取cookies、url,下载极不方便;2、音频url地址不都是能直接获取的,实测2022年的视频有SSR能直接获取window.__playinfo__全局变量,而2024年的视频不再有该全局变量,改为从接口获取。所以说为了所有视频都能爬取,继续python脚本方案的话就需要无头浏览器了,方案太重了。

浏览器插件

十分的不赶巧,浏览器插件版本(manifest.json 版本)小于v3的要被废弃了,使用低版本的会有警告。v3版本浏览器插件实现起来比较复杂,一般用户 permissions 权限是受限制的(如:不能拦截网页请求的响应内容,cookies查看受限等。)实现起来繁琐,chrome 官方的文档阅读起来也不方便。

油猴脚本(本质还是浏览器插件)

其实我们的需求十分简单,打开某个视频觉得不错,想下载下来。油猴脚本能直接在document中嵌入脚本,嵌入的脚本不受CORS、CSP限制。我们操作起来就顺手得多。下面就用油猴实现这个简单的需求。

实现

获取音视频url: 拦截xhr来获取资源的地址。

  let json = ''
  // 拦截xhr的发送
  const send = window.XMLHttpRequest.prototype.send
  window.XMLHttpRequest.prototype.send = function () {
    // 这里的拦截,只是想做额外的事情,即获取url。装饰器模式
    send.call(this, ...arguments)

    setTimeout(() => {
      const onreadystatechange = this.onreadystatechange
      this.onreadystatechange = function () {
        if (onreadystatechange) onreadystatechange.call(this, ...arguments)
        if (
          this.responseURL.startsWith(
            'https://api.bilibili.com/x/player/wbi/playurl',
          )
        ) {
          json = JSON.parse(this.responseText)
        }
      }
    }, 20)
  }

下载: 由于不存在跨域限制;cookies、referrer等防盗链限制不需要我们额外处理,直接下载即可。

  function download(url, fullName) {
    fetch(url)
      .then(res => res.blob())
      .then(blob => {
        var a = document.createElement('a')
        a.href = URL.createObjectURL(blob)
        a.download = fullName

        document.body.appendChild(a)

        a.click()
        a.remove()
      })
  }

值得注意的是B站的音、视频是分开的,需要合成。笔者的脚本支持两种模式。(目前没有完美的方案)

直接下载:分别下载视频、音频。缺点是需要手动合成(如借助ffmpeg工具)。

流式合成:借助webRTC,MediaRecorder 录制视频再下载。缺点是需完整播放视频。

 效果展示

总的来说,效果我还是满意的。(ps:深色模式,懒狗笔者还没完成)

完整脚本见:https://github.com/user-9902/scripts-for-tempermonkey/blob/main/bili_plugin/dist.js

安装等详见项目的 README.md

——————————————————  分割线  ———————————————————

2024/12/09 深色模式功能补完

2024/12/10 视频下载支持流式合成模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值