参考链接
爬取B站直播流
目录
1. 前言说明
2. 具体的分析
3. 爬取难点分析
4. 编程实现
5. 其它
6. 心得体会
一、前言说明
↶
- 前言
这个小项目也立了有一段时间,最近捣鼓了一阵子,把上次遗留下来的问题算是解决。
本次博文的目标就是从B站直播间爬取B站的直播流,相当于将B站的直播录制成视频下载到本地硬盘上的过程,当然录制直播流也有很多的软件,比如 B站录播姬 。 但是,自己实现直播流的抓取也是很有意思的,培养一些解决问题的能力。 - 说明
本次博文写作形式,主要是依据自己爬取过程中,思考的流程,写下来的。简单地说,假设如何找到要爬的人是第一步,爬取视频到本地硬盘就是最后一步,而这里恰恰准备从如何爬取视频到本地硬盘,往前推如何找要爬的人。
二、具体的分析
↶
第一步、找到爬取链接
-
随便找一个直播,打开 F12,点击 NetWork,刷新页面,加载时间最长的那个就是要抓取的链接
-
找到这个一直在加载的数据包
链接如下:
https://cn-zjhz2-cmcc-live-02.live-play.acgvideo.com/live-bvc/604475/live_3519797_5988404.flv?expires=1571389082&ssig=w2uQYxdOMz_13I31gT83zg&oi=2026667884&trid=49028817a2b2453281c3b0c0b73ead3b&pt=web&order=1&platform=web&pSession=mpEyCmnd-56GW-4E8y-1Ywj-DZ8S5HpYGX49
-
进一步分析这个链接
从链接中,可以得出这是一个 Flv 文件。从网上搜索资料查看,基本可以推测B站的直播形式大概是:HTTP+FLV 的方式。
补充说明:
业界常见的一种 HTTP 直播协议是将直播流式数据虚拟成为一个无限大的 FLV(FLASH VIDEO) 文件,并通过 HTTP 协议进行传输。客户端仅发送一次 HTTP GET 请求,请求中携带需要访问的直播流名,服务器返回 HTTP 响应,不携带消息体内容长度直接发送无限长 FLV 文件内容,或者使用 HTTP CHUNK 模式将无限长 FLV 文件按分段模式发送。客户端获得 HTTP 消息体中的 FLV 内容时即可播放。
emmm…
这不就是我们想要找到的原因,描述的跟B站的直播流传输一模一样,理论上下载这个flv文件,也是无限大的,除非 up 主下播。 -
简单验证一下,是否可以下载这个链接
① 浏览器尝试【需要更改头部】
② 简短的写一个程序
import requests
import sys
def download(url):
size = 0
chunk_size = 1024
response = requests.get(url, headers={
'Referer': 'https://live.bilibili.com',}, stream=True, verify=False)
with open('None.flv', 'wb') as file:
for data in response.iter_content(chunk_size = chunk_size):
file.write(data)
size += len(data)
file.flush()
sys.stdout.write(' [下载进度]:%.2fMB' % float(size /1024/1024 ) + '\r')
if __name__ == '__main__':
url = 'https://cn-zjhz2-cmcc-live-02.live-play.acgvideo.com/live-bvc/604475/live_3519797_5988404.flv?expires=1571389082&ssig=w2uQYxdOMz_13I31gT83zg&oi=2026667884&trid=49028817a2b2453281c3b0c0b73ead3b&pt=web&order=1&platform=web&pSession=mpEyCmnd-56GW-4E8y-1Ywj-DZ8S5HpYGX49'
download(url)
爬到的数据如下:
实际上,两种方式没什么差别,都要构造满足下载的条件,就是一些头部信息,如 User-Agent、Host、Referer等等。
总结,通过这个方式,实际上就求证了爬取的可行性,那么接下来的问题就到了如何获取链接的问题,因为,如果我们每个直播都需要这么整,也挺麻烦的。
第二步、获取 URL 链接
-
尝试在HTML代码中,搜查 URL 的踪迹
竟然如此顺利的获取到了flv的链接,不可思议。那么,我们的思路可以是:访问某个一个 UP 主的主播页面,获取HTML代码,匹配此文文本,提取 flv 链接,再用上面的方法就可以下载到 flv 直播流了。当然这个思路是可行的。 -
事实上,尝试的过程中还发现了一个特例
图没有截上,以后有机会补一张。页面中没有出现这样的匹配字样,而且链接的形式与一般的直播链接形式不一样,所以这就导致编写的程序可能会有特例出现,就是 BUG 的来源。
后续:
链接形式如:
在 HTML 代码中无法直接寻到想要的 flv 链接,因此要一劳永逸就不能采用这个办法了。 -
采取其它途径获取链接,搜索其它信息
找到一个有用的接口 api,可以返回我们想要的信息。【注意:经过我的总结和推测,如果 HTML 有嵌入链接,那么就不会有这个数据包,反过来,如果没有嵌入 HTML,那么可以抓到这个数据包,但是值得令人庆幸的一点,这个接口是通用的,无论什么直播间都能返回相应的链接】 -
查看具体返回内容
通过这种方式,我们成功地得到了下载的 URL,为了让我们更加方便的获取链接,我们还需要知道另一个参数,让我们看一下这个请求的链接:
https://api.live.bilibili.com/room/v1/Room/playUrl?cid=7734200&qn=0&platform=web
很明显,我们需要一个 cid 号,那么 cid 号怎么得到呢?让我们接着往下看。
第三步、获取拼接所需的 cid
这里省略一部分【比较麻烦的论述部分】,直接说结果吧:
事实上这里的 cid 就是房间号
https://live.bilibili.com/48267
大部分,链接中都有一串数字,如果把它拼接在下面这个链接中:
https://api.live.bilibili.com/room/v1/Room/play