爬取梨视频教程
梨视频爬取教程
1.我们首先先要查看这个地址是否能直接连接到我们所需要的视频
2.通过点击这个视频地址我们发现是直接加载在网页上面的,这个时候事情就容易多了
3.然后我们需要分析这个地址所在的a标签的规律并且使用方法找到所需要的标签数据
4.进一步检查他的转跳窗口地址并没有给全那就手动加上前面部分

import requests
from bs4 import BeautifulSoup
base_url = 'https://www.pearvideo.com/' # 实际网页是拼接而成的所以把前半部分先放好
res = requests.get('https://www.pearvideo.com/category_130') # 先向这个网页发送请求
res.encoding = 'utf-8' # 设置编码
soup = BeautifulSoup(res.text, 'lxml') # 使用bs4模块解析数据
a_tag_list = soup.select('div.vervideo-bd>a') # css选择器找得到这类div的儿子a
for a in a_tag_list: # 取出a
url_2nd = a.attrs.get('href') # 拿到href后面的链接
url = base_url + url_2nd # 拼接起来就能进入下一个网站
# 这时候已经拿到进入下一个网站的地址

我们再次分析这个页面的数据加载方式,原以为是直接加载的没想到是动态的
于是我们赶紧打开浏览器的fetch功能查看一下请求

发现朝着这个地址发送了一段可疑的请求 https://www.pearvideo.com/videoStatus.jsp?contId=1742218&mrd=0.5511860380506843

为了再次验证这个地址是否请求到的就是我们需要的视频数据将这一段地址直接复制到网页上进行二次查看

哦吼完蛋出现错误,啥也没有啊,明明请求的网址是同一个为什么会打不开嘞
这个时候的关键点就在于这个网站用了一点小小的防爬取措施
这个防爬措施的名字叫做防盗链
记录这个从哪里来的地址是有一个键的名叫referer
从刚刚这个网页的请求当中我们也能看到
这个措施的原理就是可以校验我这个请求是从哪里发出来的,如果是这个网站所允许的地方发出的就可以请求到相应的数据
这个时候的解决办法就是在发送请求的时候我们需要携带一个请求头里面包含了我们定义的referer

与此同时我们点开Response这个功能查看我们请求得到的东西究竟是不是我们想要的视频数据
由下图可知返回给我们的是一堆乱七八槽的代码,那么他真正的数据肯定还在别处
这个时候我们看到返回的东西里面有一个地址的末尾是MP4跟我们所需要的视频文件格式相同
不管有没有用先把他拿下来
https://video.pearvideo.com/mp4/short/20210713/1632464444989-15717877-hd.mp4

既然找到了可疑的网站就要去尝试利用代码向这个网站发送请求请求到网址
向这个网页www.pearvideo.com/videoStatus.jsp发送携带额外参数contid
这个时候我们发现这个地址其实是有规律的
这个contid后面的数字不正是我们前面拼接网址的时候的id嘛


经过刚刚的一通分析返回的网址究竟会不会是我们所需要的视频呢
经过我们的验证发现这个网址也不是我们真正所需要的
既然现在我们手头上面的线索都断了那么只能视频的详情页来找找有没有我们需要的东西
经过我们的研究发现再点击视频开始播放时候代码自动跳到下图这个链接的上面
https://video.pearvideo.com/mp4/third/20210914/cont-1741660-15498275-164240-hd.mp4
经过我们的验证将这个链接复制到网址网发现是可以打开的


可是这个时候问题又来了虽然我们在浏览器的elements功能里面找到的
但是他实际的加载方式是动态加载的而不是直接在网页的源代码里面
那么我们刚刚寻找到的地址就成了关键
首先是a标签里的不完整链接
video_1742218
动态加载时候请求的网址返回的链接
https://video.pearvideo.com/mp4/third/20210922/1632319265938-15498275-115401-hd.mp4
真实视频所在地址
https://video.pearvideo.com/mp4/third/20210922/cont-1742218-15498275-115401-hd.mp4
经过对比不难发现我们替换cont和他后面的一串数字句可以拿到真实的视频地址了

这个时候我们离真相不远了只需要找出上图绿色方框里面的数字就可以了
那么这个数字是从哪里来的呢
既然我们动态请求加载回复的网址是在response里面找到的那么里面就可能由我们需要的东西
果不其然在里面找到了一个systemtime这个数据是跟地址有关系的
"systemTime": "1632397145456"
既让我们知道了需要替换的数据那么直接将他们进行拼接就可以了
最后在发送请求并且保存数据就可以了

单页的爬取已经被我们搞定了现在来看看多页
我们从网页上可以看到也免得数据随着我们的滚动而出现这个时候就说明是动态加载的
打开fetch看一眼
果不其然出现的一些可疑的请求

这个时候我们看到了一些关键字start
赶紧去试一下

果不其然有我们需要的数据
而且根据返回的请求来看start数据没12分一页
那么我们可以猜测他就是我们要找的分页规律
那么写代码的时候直接将start后面的数字进行替换就行了
下面是具体的代码
import requests
from bs4 import BeautifulSoup
import os
import time
if not os.path.exists(r'犁视频'): # 如果存储文件夹不存在
os.mkdir(r'犁视频') # 就创建一个
def pear_video(n):
# base_url = 'https://www.pearvideo.com/' # 实际网页是拼接而成的所以把前半部分先放好
res = requests.get('https://www.pearvideo.com/category_loading.jsp',
params={'reqType': 5,
'categoryId': 10,
'start': n}) # 先向这个网页发送请求
res.encoding = 'utf-8' # 设置编码好习惯
soup = BeautifulSoup(res.text, 'lxml') # 解析
a_tag_list = soup.select('div.vervideo-bd>a') # css选择器找得到这类div的儿子a
for a in a_tag_list: # 取出a
url_2nd = a.attrs.get('href') # 拿到href后面的链接
# url = base_url + url_2nd # 拼接起来就能进入下一个网站
# print(url_2nd) # video_1742218
headers = {'Referer': 'https://www.pearvideo.com/%s' % url_2nd} # 先定义好防爬的请求头
cont_id = url_2nd.split('_')[-1] # 分割取到所需字符
res1 = requests.get('https://www.pearvideo.com/videoStatus.jsp',
headers=headers,
params={'contId': cont_id}) # 向动态加载内部网页发送请求
almost_url = res1.json().get('videoInfo')['videos']['srcUrl'] # 通过字典取值拿到返回的网址数据 两种取值方法都试试
sys_time = res1.json()['systemTime'] # 拿到得到网址中想要替换掉的字符串
# 这样搞定了前面还鱼龙混杂的问题 现在只需要专心解决后面的那串数字怎么替换即可
'''
得到网址
https://video.pearvideo.com/mp4/third/20210922/1632319265938-15498275-115401-hd.mp4
最终目标
https://video.pearvideo.com/mp4/third/20210922/cont-1742218-15498275-115401-hd.mp4
替换之后
https://video.pearvideo.com/mp4/third/20210922/cont-1742218-15498275-115401-hd.mp4
'''
# 在网页的response里出现过这个数字 是系统时间
final_url = almost_url.replace(sys_time, 'cont-%s' % cont_id) # 通过字符串替换得到最终网址
# print(final_url)
# break
res2 = requests.get(final_url) # 发送请求
name = cont_id + '.mp4' # 给文件名加上后缀
media_add = os.path.join(r'犁视频', name) # 拼接文件路径
with open(media_add, 'wb') as f: # 以二进制写模式打开
f.write(res2.content) # 直接二进制写入
print('%s下好啦' % name) # 加个完成提示
time.sleep(1) # 加一个延迟免得给人网站弄崩了
for n in range(0, 60, 12): #根据分页规律定义一个等差数列12为一页
pear_video(n)

浙公网安备 33010602011771号