错误写法
如果我们用xpath爬取视频,只需要检阅元素,
我们会查找到视频地址,理论上会直接获取到,但结果返回的是空列表:
我们直接看页面源代码,搜索<video
,结果是查找不到的,这是因为页面源代码是固定好的,而整个页面是不断更新的,因此多是用json写的,在开发者模式下, 元素
是基于页面源代码动态更新的。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。自从有了ajax之后,我们就可以实现异步的加载网页。
什么叫异步?
异步,异嘛,不同的意思,这里也就是指不跟浏览器加载执行网页代码的步伐一致,也就是说在一个网页中需要用户操作来触发执行代码,而不是整个网页代码一次性执行完毕。(这里的用户操作是指在同一个网页下面请求代码执行渲染,而不是让浏览器直接跳转渲染另一个页面)
详细解释看这里
因此这种写法是获取不到视频链接的
正确写法:
我们先看一下视频链接:
在开发者模式下,点击XHR(相当于一个接口,通过这个接口,我们可以对网站进行更新而不需要更改页面源代码,这就是为什么有的内容我们在页面源代码查找不到),我们会看到一个json文件:
最底层有一个关于video的srcurl
我们将这个srcurl打开,结果是404。
对比一下下面的两个链接:
只需要将"20211112/"到"-15192550"之间的替换即可,那么替换的部分我们会发现,就是systemtime
因此我们通过请求这个json文件的url获取
报错
常规请求:url,headers=headers
但返回的结果是:
我们向下翻,会看到Referer:
这是一个防盗链,比如说目录是1->2->3,如果消失,我们就无法从3溯源到1,因此,我们要在headers
里加一个Referer,注意headers是一个字典,添加要有,
连接,这样我们就能够获取到需要的信息了
获取信息并处理
我们返回json字典形式,并获取systemTime
和srcUrl
videoStatusurl = "https://www.pearvideo.com/videoStatus.jsp?contId=1745747&mrd=0.878842147502072"
req = requests.get(videoStatusurl,headers=headers)
# json 返回字典 寻找需要的url
dic = req.json()
srcurl = dic['videoInfo']['videos']['srcUrl']
systemtime = dic['systemTime']
获取srcUrl 后,将srcurl
中的systemTime
替换成contId:
contId 是视频的地址后面的数字,也等同于XHR下json文件的Payload
接下来将contId把systemTime替换掉就可:
# 以 f开头表示在字符串内支持大括号内的python 表达式
#srcurl = srcurl.replace(systemtime,"cont-"+contId)
srcurl = srcurl.replace(systemtime,f"cont-{contId}")
完整代码:
code:
# 在页面元素中可以查找到,但在页面源代码找不到视频,
# 这是后期通过js脚本加入的,因此在xpath会返回空列表
# 开发者工具是实时的,页面源代码是固定好的源代码
import re
import requests
import time
from xml import etree
# 获取contid
# 拿到videostatus 返回的json. -> srcURL
# srcURL 修改调整
# 下载视频
#获取视频网址
url = "https://www.pearvideo.com/video_1745747"
contId = url.split('_')[1]
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Edg/96.0.1054.29'
# Referer 防盗链 : 1->2->3 2消失无法溯源,Referfer 可以溯源
# 字典加,
,'Referer': 'https://www.pearvideo.com/video_1745747'
# 'Referer': url 也可
}
videoStatusurl = "https://www.pearvideo.com/videoStatus.jsp?contId=1745747&mrd=0.878842147502072"
req = requests.get(videoStatusurl,headers=headers)
# json 返回字典 寻找需要的url
dic = req.json()
srcurl = dic['videoInfo']['videos']['srcUrl']
systemtime = dic['systemTime']
# 以 f开头表示在字符串内支持大括号内的python 表达式
#srcurl = srcurl.replace(systemtime,"cont-"+contId)
srcurl = srcurl.replace(systemtime,f"cont-{contId}")
with open("梨视频.mp4",'wb') as f:
f.write(requests.get(srcurl).content)
print("over")
req.close()
#https://video.pearvideo.com/mp4/third/20211112/cont-1745747-15192550-115119-hd.mp4
#https://video.pearvideo.com/mp4/third/20211112/1637635409563-15192550-115119-hd.mp4