前言
众所周知,B站的视频是以Blob的方式分断传输视频的,网上也有很多使用拼接视频来达到下载的目的的,但是这样的效率很低,这篇文章提供了三种其它的思路去下载小破站的视频。
开发环境
python 3.7.3
一、模拟手机
谷歌浏览器有模拟手机的功能,直接切到手机模式去打开视频播放页,就能拿到视频的源URL。
OK,这里就有源地址了,说明我们就拿的到,看看它响应给我们的内容有什么:
var options = {
aid: 929284665,
bvid: 'BV1RK4y1Q76M',
cid: 300249317,
readyPoster: '//i1.hdslb.com/bfs/archive/e3653786d363a4e37dc01f5c8f1dd88791250472.jpg@480w_270h_1c',
readyVideoUrl: 'https://cn-zjhz-cmcc-v-01.bilivideo.com/upgcxcode/17/93/300249317/300249317-1-16.mp4?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfq9rVEuxTEnE8L5F6VnEsSTx0vkX8fqJeYTj_lta53NCM=&uipk=5&nbs=1&deadline=1613912417&gen=playurl&os=vcache&oi=3083915405&trid=51606b49936a4e51a082be26ad4c9d00h&platform=html5&upsig=4c15f223ebed1d8cd7d4ca88ae18fb96&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&cdnid=4059&mid=56446197&logo=80000000',
readyDuration: 211,
noRecommend: gqs('from') == 'game'
}
一眼就看到视频源地址了,代码实现获取源地址。
# 获取视频url
def get_video_url(url, headers):
# GET方式请求网站
req = request.Request(url, headers=headers, method="GET")
try:
#获取到HTMl
response = request.urlopen(req).read().decode('utf-8')
except error.HTTPError as e:
print(e)
print('\r\n' + url + 'download failed' + '\r\n')
# 正则表达式提取视频URL
video_url = re.search(r"readyVideoUrl: '(.*)?'", response)[0][16: -1]
return video_url
拿到视频源地址,想干嘛就能干嘛了。但是这样的方法有个大缺点,就是视频的清晰度是360P的,属实有点低。
二、浏览器的方法
尝试干掉浏览器中video标签的src内容,如下图,再次刷新页面。
<video preload="auto" src="blob:https://www.bilibili.com/f6604c86-c729-4811-b643-8f03117524c8"></video>
video标签里的内容又重新加载出来了,并且Network里出现了一条不太眼熟的请求。
https://api.bilibili.com/x/player/playurl?cid=300249317&bvid=BV1RK4y1Q76M&qn=80&type=&otype=json&fourk=1&fnver=0&fnval=80
看响应内容:
"video": [
{
"id": 80,
"baseUrl": "https://xy183x211x222x233xy.mcdn.bilivideo.cn:4483/upgcxcode/17/93/300249317/300249317-1-30080.m4s?expires=1613913782&platform=pc&ssig=FIiyAdg2RQ1B2vConj9UCw&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&mcdnid=1001366&mid=56446197&orderid=0,3&agrr=0&logo=A0000001",
"base_url": "https://xy183x211x222x233xy.mcdn.bilivideo.cn:4483/upgcxcode/17/93/300249317/300249317-1-30080.m4s?expires=1613913782&platform=pc&ssig=FIiyAdg2RQ1B2vConj9UCw&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&mcdnid=1001366&mid=56446197&orderid=0,3&agrr=0&logo=A0000001",
"backupUrl": [
"https://xy183x211x222x212xy.mcdn.bilivideo.cn:4483/upgcxcode/17/93/300249317/300249317-1-30080.m4s?expires=1613913782&platform=pc&ssig=FIiyAdg2RQ1B2vConj9UCw&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&mcdnid=1001380&mid=56446197&orderid=1,3&agrr=0&logo=60000001",
"https://cn-jssz-cmcc-v-06.bilivideo.com/upgcxcode/17/93/300249317/300249317-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1613913782&gen=playurl&os=vcache&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&platform=pc&upsig=27e3b8e1d5c6ce95884b710c549cafcc&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&cdnid=5204&mid=56446197&orderid=2,3&agrr=0&logo=40000000"
],
"backup_url": [
"https://xy183x211x222x212xy.mcdn.bilivideo.cn:4483/upgcxcode/17/93/300249317/300249317-1-30080.m4s?expires=1613913782&platform=pc&ssig=FIiyAdg2RQ1B2vConj9UCw&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&nfc=1&nfb=maPYqpoel5MI3qOUX6YpRA==&mcdnid=1001380&mid=56446197&orderid=1,3&agrr=0&logo=60000001",
"https://cn-jssz-cmcc-v-06.bilivideo.com/upgcxcode/17/93/300249317/300249317-1-30080.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1613913782&gen=playurl&os=vcache&oi=3083915405&trid=746221becc7249988cb157cc2f284567u&platform=pc&upsig=27e3b8e1d5c6ce95884b710c549cafcc&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&cdnid=5204&mid=56446197&orderid=2,3&agrr=0&logo=40000000"
],
出现视频的源地址了,剩下的就是花点儿时间琢磨一下这条url中的参数有什么作用就行了,所需要的参数必须有视频bvid和cid,qn是清晰度。bvid就是视频的BV号,直接获取就行,cid则需要继续找。接着看下面这条请求。
https://api.bilibili.com/x/player/pagelist?bvid=BV1RK4y1Q76M&jsonp=jsonp
这个请求响应内容包含了视频CID,小标题,分辨率等信息。
{
"code": 0,
"message": "0",
"ttl": 1,
"data": [
{
"cid": 300249317,
"page": 1,
"from": "vupload",
"part": "横屏",
"duration": 106,
"vid": "",
"weblink": "",
"dimension": {
"width": 3840,
"height": 2160,
"rotate": 0
}
},
{
"cid": 300249655,
"page": 2,
"from": "vupload",
"part": "竖屏手机版",
"duration": 105,
"vid": "",
"weblink": "",
"dimension": {
"width": 1080,
"height": 1920,
"rotate": 0
}
}
]
}
需要的东西够了,开始代码实现获取视频源地址。
class BiliBili:
# 构造请求头
__headers = {
"User_Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36",
"referer": "https://www.bilibili.com/",
}
def __init__(self, url):
self.url = url
# 获取BVID
def __bvid(self):
bvid = self.url.split('/')[len(self.url.split('/')) - 1]
if '?' in bvid:
bvid = bvid.split('?')[0]
return bvid
# 获取CID
def __cid(self):
url = f"https://api.bilibili.com/x/player/pagelist?bvid={self.__bvid()}&jsonp=jsonp"
req = request.Request(url, headers=self.__headers, method="GET")
reponse = request.urlopen(req).read().decode("utf-8")
return json.loads(reponse)['data'][0]["cid"]
# 设置cookie
def set_cookie(self, cookie):
self.__headers['cookie'] = cookie
# 获取视频url
def video_url(self):
url = f"https://api.bilibili.com/x/player/playurl?avid=&cid={self.__cid()}&bvid={self.__bvid()}&qn=120&type=&otype=json"
req = request.Request(url, headers=self.__headers, method="GET")
response = request.urlopen(req).read().decode("utf-8")
return json.loads(response)['data']['durl'][0]['url']
同样,获取到了视频的源地址,剩下的就个人发挥了。
三、哔哩哔哩APP
其实哔哩哔哩有桌面客户端的,只是用的人不多,也没见B站推广。如果仅仅是下载视频的需求的话,直接用客户端就可以,相当简单快捷。
直接在Windows电脑的微软商店去搜索“哔哩哔哩”,免费下载安装里面的“哔哩哔哩动画”,喜欢哪个视频直接动动发财的小手点一下下载按钮即可。
总结
以上就是B站视频的三种下载方式了,完整的代码我放在Github上,请移步:https://github.com/KingJeeWhy/bilibili。另外,谢谢各位看官点的赞了。最后,文章内容仅作为交流和学习,请不要用做不良用途,希望小破站能越来越好。