ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!

实现方式:

番剧是以ep号为准的,而且每一集都对应一个独立的ep号。B站友善的一点在于1-x集ep号都是连着的,所以连续爬多集也是相当方便。
原理其实和bv号视频一模一样,原理的话可以参考之前的文章:完全小白篇-使用Python爬取B站视频(普通视频)——我们需要获取的就是vedio、audio对应的baseUrl。

分析网页:

非会员访问大会员特权的视频时,检查网页是得不到vedio和audio的(不信你可以试试)。对于非大会员特权的视频,我们在普通账户情况下访问才会得到这两个信息。一般来讲,非大会员能看的番剧量显然受限!购买大会员直接下载吧,好像网上还有bilibili下载助手,不过这不是咱的目的。
那么现在,我们是“大会员”用户!可是我们单纯只模仿浏览器身份(改写user-agent信息)的话显然就会被服务器视为非会员,明明身为大会员却爬不到资源,岂有此理。。。
所以这一次分析的重点就在于比较非会员和大会员访问剧集的区别。

非会员访问结果

退出账号,访问大会员特权视频,网页首个获取数据包的就是网页源代码。现在的问题就是非会员获得的网页源代码和大会员是不同的,所以这个数据包的request头信息就是分析的目标。

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第1张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第2张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第3张图片

大会员访问结果

大会员获得的网页源代码显然不同,虽然和bv号的网页代码有稍微的差别,但是从之前的分析来看,baseUrl即base_url,大会员的特殊性就在这。所以必须要分析request header到底有什么区别。

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第4张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第5张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第6张图片

差异分析

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第7张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第8张图片

挺明显的,是cookie的差异!所以只需要通过改写cookie信息,就可以模仿大会员去访问需要特权的番剧剧集了!

def getHtml(baseurl):
basecookie = "_uuid=53E3C6FE-1D8A-F3B2-7E23-ACA84A536D4F63234infoc; buvid3=D401D951-D96A-4691-A664-CDAF15B0234D53941infoc; CURRENT_FNVAL=16; rpdid=|(J|)JulY|Yk0J'ulmuJk)l~R; sid=a9w7482a; finger=-166317360; LIVE_BUVID=AUTO8715959029630612; PVID=3;"
head = { #模拟浏览器身份头向对方发送消息
"cookie": basecookie+"_jct=2b7857b0d0b011eaa7f77ea539b9b3b7; DedeUserID=391625457; DedeUserID__ckMd5=accdac0e7e5f4f54; SESSDATA=a7c5c1cc%2C1611478568%2C56408*71; bili_jct=fe0e50c7ef84f6938d345f2b0c5e31d4",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
try:
response = requests.get(url = baseurl, headers = head)
if response.status_code==200:
return response.text
except:
print("请求失败")

以下是完整代码:

import requests
from requests import RequestException
from lxml import etree
import re
import os
import json
import subprocess
import urllib3
urllib3.disable_warnings()
def getHtml(baseurl):
basecookie = "_uuid=53E3C6FE-1D8A-F3B2-7E23-ACA84A536D4F63234infoc; buvid3=D401D951-D96A-4691-A664-CDAF15B0234D53941infoc; CURRENT_FNVAL=16; rpdid=|(J|)JulY|Yk0J'ulmuJk)l~R; sid=a9w7482a; finger=-166317360; LIVE_BUVID=AUTO8715959029630612; PVID=3;"
head = { #模拟浏览器身份头向对方发送消息
"cookie": basecookie+"_jct=2b7857b0d0b011eaa7f77ea539b9b3b7; DedeUserID=391625460; DedeUserID__ckMd5=accdac0e7e5f4f56; SESSDATA=a7c5c1cc%2C1611478568%2C56408*71; bili_jct=fe0e50c7ef84f6938d345f2b0c5e31d4",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.56 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.56"
}
try:
response = requests.get(url = baseurl, headers = head)
if response.status_code==200:
return response.text
except:
print("请求失败")
def main():
print("欢迎来到bilibili爬资源小程序,接下来让我们开始吧\n(只针对番剧,您现在正在使用账户名为xxx的用户的会员cookie)")
judge = input("你想获得一系列(y)视频还是一个单一(N)视频? [y/N]\n")
if judge == "y":
max = int(input("输入该系列视频的总数: "))
ep = int(input("输入第一集的ep号: "))
for ep in range(ep,ep+max):
baseurl = "https://www.bilibili.com/bangumi/play/ep"+str(ep)
getVideo(baseurl,ep)
else:
ep=input("如果是系列视频,请任选一集输入视频ep号\n")
baseurl = "https://www.bilibili.com/bangumi/play/ep"+str(ep)
getVideo(baseurl,ep)
os.system("pause")
def getVideo(baseurl,ep):
html = getHtml(baseurl)
# 找到视频的标题
pattern = r'\
result = re.findall(pattern, html)[0]
pattern = r'\

.*\

'
title = re.findall(pattern, html)[0]
print(title)
temp = json.loads(result)
print(("开始下载--->")+title)
title = str(ep)
try:
video_url = temp['data']['dash']['video'][0]['baseUrl']
audio_url = temp['data']['dash']['audio'][0]['baseUrl']
fileDownload(homeurl=baseurl, url=video_url, title=title, typ=0)
fileDownload(homeurl=baseurl, url=audio_url, title=title, typ=1)
try:
combine(title)
except:
print("对不起,您的电脑中未安装ffmpeg,不予享受合成服务,您可以尝试使用格式工厂等其他方式\n")
except Exception:
vedio_url = temp['data']['durl'][0]['url']
fileDownload(homeurl=baseurl, url=video_url, title=title, typ=0)
def fileDownload(homeurl, url, title, typ):
# 添加请求头键值对,写上 refered:请求来源
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
}
headers.update({'Referer': homeurl})
if typ==0:
print("正在下载视频")
filename = "./"+title+".flv"
else:
print("正在下载音频")
filename = "./"+title+".mp3"
res = requests.Session()
# 指定每次下载1M的数据
begin = 0
end = 2048*4096 - 1
flag = 0
while True:
# 添加请求头键值对,写上 range:请求字节范围
headers.update({'Range': 'bytes=' + str(begin) + '-' + str(end)})
# 获取视频分片
res = requests.get(url=url, headers=headers,verify=False)
if res.status_code != 416:
# 响应码不为为416时有数据
begin = end + 1
end = end + 2048*4096
else:
headers.update({'Range': str(end + 1) + '-'})
res = requests.get(url=url, headers=headers,verify=False)
flag=1
with open(filename, 'ab') as fp:
fp.write(res.content)
fp.flush()
if flag==1:
fp.close()
break
print("下载完成!")
def combine(title):
videopath = "./"+title+".flv"
videopath = os.getcwd()+"\\"+title+".flv"
audiopath = "./"+title+".mp3"
audiopath = os.getcwd()+"\\"+title+".mp3"
outpath = "./"+title+".flv"
outpath = os.getcwd()+"\\"+title+".mp4"
subprocess.call(("C:/ffmpeg-win64-static/bin/ffmpeg -i " + videopath + " -i " + audiopath + " -c copy " + outpath).encode("utf-8").decode("utf-8"),shell=True)
os.remove(videopath)
# os.remove(audiopath)
if __name__ == "__main__":
main()

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第9张图片

ffmpeg失败 python_用Python爬取B站大会员番剧集,B站的番剧还是很好看的!_第10张图片

那样调用getvedio即可。
这一次工作量其实比爬bv号轻松一些,用python爬资源,重中之重还是分析网页。最终获取的资源应该都是1080P+左右了,真正的高清资源,清晰度非常好评!与其在网上搜不如自己爬下来收藏。

源码已备好,完整项目代码获取加群:1136192749

你可能感兴趣的:(ffmpeg失败,python)