def getDetails(arcUrl): # 获取视频长度,标题,子视频数,打印视频质量选项,让用户输入,获得quailty(顺便修改refer)
global quality
global headers
global fps
global quality
global title
global pages
global titles
headers["Referer"] = arcUrl # 修改referer
driver.get("view-source:" + arcUrl) # 浏览器黑魔法
data = driver.page_source
"""fp = open("data.txt", 'w')
fp.write(data)
fp.close()"""
titleScripText = re.findall("window.__INITIAL_STATE__=.*?;\(function\(\)", data, re.S)[0]
titleScripText = titleScripText.replace("window.__INITIAL_STATE__=", '')
titleScripText = titleScripText.replace(";(function()", '')
"""fp = open("datatitle.txt", 'w')
fp.write(titleScripText)
fp.close()"""
titleScripText = json.loads(titleScripText)
title = titleScripText['videoData']['title']
print("本视频为: %s " % title)
pages = len(titleScripText['videoData']['pages'])
if pages != 1:
if not int(input("其中包含%d个视频,是否全部下载[1=是,0=否(请输入数字,默认只下载第一个视频)]:" % pages)):
titles.append(titleScripText['videoData']['pages'][0]['part'])
pages = 1
else:
print("\n视频列表为:")
for i in range(pages):
titles.append(titleScripText['videoData']['pages'][i]['part']) # 如果titles不为空那么需要下载titles内所有视频
print('--' + titles[i])
else:
titles.append(titleScripText['videoData']['title'])
qualityScripText = re.findall("window.__playinfo__=.*?/script", data)[0]
qualityScripText = qualityScripText.replace("window.__playinfo__=", '')
qualityScripText = qualityScripText.replace("""<span class="html-tag"></script""", '')
"""fp = open("dataquality.txt", 'w')
fp.write(qualityScripText)
fp.close()"""
qualityScripText = json.loads(qualityScripText) # 视频信息解析完成
print("\n本视频清晰度有:")
for i in range(len(qualityScripText['accept_description'])):
print(i, qualityScripText['accept_description'][i])
qualityValue = int(input("请输入序号以选择下载视频的清晰度(1080+需要大会员): "))
quality = qualityValue
qualityValue = qualityScripText['accept_quality'][qualityValue]
if qualityValue == 112:
fps = 60
print("清晰度选择完成")
这里无非就是通过正则表达式提取页面信息罢了。
但是,还是有几点要注意的:
1.审查元素与查看网页源代码的区别
在提取多P视频信息时,有一个window.__INITIAL_STATE__ 项属于javascript,包含着其他视频的题目,个数等信息。它在网页源代码中存在,而在审查元素中却消失了。
网页源代码是服务器直接发给浏览器的代码,浏览器将代码渲染执行后变为审查元素并在浏览器上展示出来。selenium会尽力模仿浏览器的行为,driver.page_source 提取的网页元素基本与审查元素等价,而不是网页源代码。
我搜索了很多地方,也没能找到那个库或方法能直接将网页源代码提取出来,因为urllib是不会处理javascript的,自然被排除在外,处理javacript最好的方法貌似就是selenium,但它不会返回网页源码,只会返回处理过的源码。
这里我想到一点,Chrome浏览器中在任何链接前加入view-source: 后打开会直接显示当前链接获得的源码,所以我抓去这一页面的page_source,最终将我所需要的信息提取出来了。
2.header的修改
headers = {
'User-Agent': '[]',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-cn',
'Referer': 'https://www.bilibili.com',
'Origin': 'https://www.bilibili.com',
'Accept': '*/*',
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
最开始获得bilibili下载链接调用下载函数下载视频时,经常会报403,954等错误。bilibili对于下载视频的请求似乎一定要加上header才能成功访问(证明你是个浏览器,而不是机器人之类的)。然而加上header后访问失败的概率依然不低。
经过仔细研究,发现对于每个视频的下载,所提交的header中referer都是有变化的。referer会变为当前视频链接。我将每个视频的referer更改后视频下载的成功率飙升,基本没再遇到下载问题。所以说header中的referer是一定要修改的。
当然,这里的header,referer之类的都是下载视频时需要用到的东西,如果不懂,将下载之前我会再详细讲。