Blog Detail

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

    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里的视频