编写直播视频下载工具

        某种程度上说,这个工具写得并不成功,适用性较差,不过过程中遇到的许多问题还是比较有探讨价值的,所以分享出来以供参考和交流。

        【需求说明】

        关于直播视频的下载,网上可以搜到一些,比如用Fiddler脚本抓包ts保存到本地再合并,但这些方式对小白而言太难了,所以就想着写个傻瓜化的工具。程序的界面设计如下。

        界面比较简单,左侧可以设置“直播地址、下载目录、保存频率”以及“请求头user-agent”;右侧是直播视频展示区(iframe标签)。

        【踩坑01】

        此处以百度为例,当试图在iframe中打开百度页面时,报了个错:“Refused to display [URL] in a frame because it set 'X-Frame-Options' to 'sameorigin'.”

         X-Frame-Options 响应头是用来给浏览器指示允许一个页面可否在 <frame>、<iframe>、<embed> 或者 <object> 中展现的标记。

可选值

作用

DENY

该页面不允许在frame中展示

SAMEORIGIN

该页面可以在相同域名页面的frame中展示

ALLOW-FROM

该页面可以在指定来源的frame中展示

ALLOWALL

该页面允许全部来源域名的frame展示

        根据这个标识的特点,修改思路便有了:当网络请求响应头返回时对其中的该标识的值进行修改,修改后再嵌套就可规避该错误。相关代码如下

let filters = {urls: ['*://*/*']}
session.defaultSession.webRequest.onHeadersReceived(filters, (details, callback) => {
    details.responseHeaders['X-Frame-Options'] = 'AllowAll'
    callback({cancel: false, responseHeaders: details.responseHeaders})
})

        【踩坑02】

        此处以抖音直播为例,当使用iframe打开时,报了错

         这是因为响应头中设置了内容安全策略,该标识限制了iframe嵌套需要遵循的规则。

        Content-Security-Policy字段有若干指令,可以设置指定的策略允许的源。其值的格式为: [指令] <source> ...; [指令] <source> ...;...

指令

限制范围

frame-ancestors

<frame>,<iframe>,<object>,<embed>或<applet>

worker-src

Worker SharedWorker ServiceWorker

script-src

<script>

        这个标识和之前的标识类似,修改思路:当网络请求响应头返回时对其中的该标识的值进行修改,修改后再嵌套就可规避该错误。相关代码如下

details.responseHeaders['content-security-policy'] = ''

        【踩坑03】

        有的网站只允许在微信环境中进行访问,这个分情况,如果只是微信的user-agent校验可以通过修改请求头&本地标识来解决;如果是页面代码逻辑控制的,便没太好的办法(修改原始js数据会破坏业务逻辑,也超出了本程序傻瓜化的初衷)。

        修改请求头的user-agent代码:

session.defaultSession.webRequest.onBeforeSendHeaders(filters, (details, callback) => {
    details.requestHeaders['User-Agent'] = [微信user-agent]
    callback({cancel: false, requestHeaders: details.requestHeaders})
})

        修改程序的navigator.userAgent代码:

mainWindow.loadURL('app://./index.html', {
    userAgent: [微信user-agent]
})

        【踩坑04】

        通过Electron拦截网络请求时,在数据返回的各个阶段都无法拿到响应数据的responseBody,更尴尬的是,其它的数据都有,唯独没有body体。网上搜了很久,资料很少,没有找到有效的办法。

        所以,退而求其次,当接口响应数据返回以后,用fetch再请求一次资源(还好有浏览器缓存,所以基本上也还凑合)。

        相关代码:

this.tsIndex = 0
let filters = {urls: ['*://*/*']}
session.defaultSession.webRequest.onCompleted(filters, (details) => {
    let baseUrl = details.url.split('?')[0]
    if (/\.ts$/.test(baseUrl) && !this.downloadDict[baseUrl]) {
        let index = this.tsIndex
        this.tsIndex++
        this.downloadDict[baseUrl] = 1
        console.log(index, details.url)
        fetch(details.url, {method: 'get', responseType: 'arraybuffer'}).then(res => {
            return res.arrayBuffer()
        }).then((ab) => {
            this.dataList[index] = ab
        })
    }
})

        【功能测试】

        测试平台:芒果TV、百度直播、抖音直播

        测试结果:芒果TV可以正常抓取;百度直播抓取到的视频数据不能播放;抖音直播抓取不到数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半吊子伯爵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值