抓取视频网站的流媒体数据

2021-12-30 11:14:34 浏览数 (1)

1. 多媒体流协议RTSP,MMS简介

2. 使用VLC软件保存捕获的网络流

首先下载并安装VLC软件

然后,添加网络串流地址

打开VLC,点击媒体 -> 打开网络串流,添加网络流媒体链接: rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4

选择保存到文件,选中在"本地显示":

选择文件存放目录:

选择文件的格式,这个根据网络流媒体的格式选择,这里是MP4

串流输出:

等待一段时间,关闭VLC软件后,就可以打开MP4文件

保存的视频文件:

2. 捕获B站的网络视频流并保存

2.1 使用Fiddler分析B站视频流

首先打开Fiddler,使用Ctrl X清屏,然后在浏览器播放B站视频

然后在Fiddler处查看数据包,左边是图标,蓝白色的图标表示的就是视频或者音频文件,点击它可以在右下方的Headers里看到这个数据包的内容的长度。

2.2 利用Composer下载完整内容

打开右侧Composer

抓取完整的数据包内容,上面的Content-Range里的781414表示完整的视频内容的长度,而1235-287168只是这一段数据表示的视频内容,所以我们要抓取完整的0-781414的视频内容:

点击左侧数据包,拖动它到右侧:

这个数据包只请求1235-287168段的视频数据,修改它为0-781414:

点击Execute,回到左侧,拉到最下方,可以看到有一个新的视频数据包,右键它,点击 Save→Response→Response Body 保存它:

文件默认的后缀名为m4s.txt,修改文件的后缀名为mp4:

接下来以同样的方式处理第二个数据包,这是音频文件:

得到audio.mp4:

2.3 使用VLCPlayer查看下载的视频文件

可以直接播放,但是音频文件没有合并,所以没有声音,可以用ffmpeg合并两个文件

2.4 爬取B站视频

使用BiliBili的视频流API下载

代码语言:javascript复制
import json
import requests
from fake_useragent import UserAgent
import re
​
# setting
​
# 自动最大分辨率 -> 0, 1080p -> 1, 720p -> 2, 480p -> 3, 360p -> 4 ,1080  -> 5
type = 0
​
# 编码格式 avc -> 0, hev -> 1
codecs = 0
​
#cookie
cookie = ''
​
# 下载大小(Byte为单位,None为全部)
byte = None
# byte = '0-9999'
​
​
url1='https://api.bilibili.com/pgc/player/web/playurl?fnval=80&cid={c}'
url2='https://api.bilibili.com/x/player/playurl?fnval=80&avid={a}&cid={c}'
​
class VideoList:
​
    headers={
        'User-Agent': '',
        'referer': '',
        'cookie': cookie
    }
​
    def __init__(self,url,part=[0]):
        self.url=url
        self.part=part
        
    def download(self):
        self.headers['User-Agent'] = str(UserAgent().random)
        try:
            self.html = requests.get(self.url,self.headers).text
        except Exception:
            print('链接失败')
            return None
​
        if re.findall(r'.bilibili.com/video/BV',self.url) != [] or re.findall(r'.bilibili.com/video/av',self.url) != []:
            return self.video()
        elif re.findall(r'.bilibili.com/bangumi/play/',self.url) != []:
            return self.bangumi()
        else:
            print('url无效')
            return None
​
    def bangumi(self):
        json_ = json.loads('{' re.search(r'"epList":[. ?]',self.html).group() '}')
        self.headers['referer']=self.url
​
        for i in self.part:
            try:
                cid = json_['epList'][i]['cid']
            except Exception:
                print('分p不存在')
                break
            self.headers['User-Agent'] = str(UserAgent().random)
            js = json.loads(requests.get(url1.format(c=cid),headers=self.headers).text)
            js['referer'] = self.url
            js['part'] = i
            yield js
​
    def video(self):
        json_ = json.loads('{' re.search(r'"aid":d ',self.html).group() '}')
        aid = json_['aid']
        json_ = json.loads('{' re.search(r'"pages":[. ?]',self.html).group() '}')
        self.headers['referer']=self.url
​
        for i in self.part:
            try:
                cid = json_['pages'][i]['cid']
            except Exception:
                print('分p不存在')
                break
            self.headers['User-Agent'] = str(UserAgent().random)
            js = json.loads(requests.get(url2.format(a=aid,c=cid),headers=self.headers).text)
            js['referer'] = self.url
            js['part'] = i
            yield js
        
​
class Download:
​
    headers={
        'User-Agent': '',
        'referer': '',
        'cookie': cookie
    }
​
    def __init__(self,js):
        self.js=js
​
    def download(self,path,type = 0,codecs = 0,byte = None):
        self.headers['User-Agent'] = str(UserAgent().random)
        self.headers['referer'] = self.js['referer']
        p = str(self.js['part'])
​
        if 'data' in self.js:
            self.js=self.js['data']
        else:
            self.js=self.js['result']
​
        id = self.js['dash']['video'][0]['id']
        if type == 1:
            id = 80
        elif type == 2:
            id = 64
        elif type == 3:
            id = 32
        elif type == 4:
            id = 16
        elif type == 5:
            id = 112
        elif type != 0:
            print('type参数错误')
            return None
        code = 'avc'
        if codecs == 1:
            code = 'hev'
        elif codecs != 0:
            print('codecs参数错误')
            return None
​
        js_movie = None
        for i in self.js['dash']['video']:
            if i['id'] == id and re.findall(code,i['codecs']) != []:
                js_movie = i
                break
        js_audio = self.js['dash']['audio'][0]
        if js_movie == None:
            print('指定元素相关视频不存在')
            return None
​
        if byte!=None:
            self.headers['range'] = 'bytes=' byte
​
        vid = self.headers['referer'].split('/')[-1]
        with open(path vid '_' p '.mp4','wb ') as file1, open(path vid '_' p '.mp3','wb ') as file2:
            print('下载中','网址:' vid '   ' '分p:' p)
            file1.write(requests.get(js_movie['base_url'],headers=self.headers).content)
            file2.write(requests.get(js_audio['base_url'],headers=self.headers).content)
            print('下载成功')
​
​
​
# 需要下载的视频网址
url = 'https://www.bilibili.com/video/BV1ty4y1H7H8'
# 需要下载的视频p数列表(番剧则为集数)
part = range(0,1)
# 下载路径
path = 'video/'
​
# 运行此文件即可下载
if __name__ == "__main__":
    vl = VideoList(url,part)
    for i in vl.download():
        dl = Download(i)
        dl.download(path,type = type,codecs = codecs,byte = byte)

爬取结果:

3. 参考

[1] b站视频下载接口分析

[2] 爬取B站直播流 - http flv的相关研究

[3] ffmpeg合并m4s文件

[4] 【Fiddler】利用Fiddler下载保存Bilibili里的视频

0 人点赞