好吧,我们前面爬取图片发现使用了线程池后,其实我们的效率提高不是这么明显。那我们就来试一试爬取视频吧。因为不同的网站对视频的反爬的策略都不尽相同,所以我们这里讲的示例并没有普世的意义。唯一普世的做法是好好分析视频网址的存放地址。
需求
首先来讲一讲我们这次爬取的视频。
我们这次爬取的视频是梨视频娱乐模块最热的视频
即图片里的前三个(但我们打开抓包工具时,又发现其实是 4 个视频,不管是几个,关系都不大)
分析
首先我们先随便定位一个视频,得到如下的网页源码
我们发现这里的 a 标签下面有一个超链接,然后我们点击这个超链接,跳转网页,来到了视频播放页。注意这个超链接的内容,后面要用到。
接着我们再一次试图定位时,却发现我们找不到 .mp4 的网页。怎么办呢?
没事,我们可以试着播放视频再进行定位。下面就是见证奇迹的时候了。
当然,以我们目前所学是拿不到在这个动态加载的数据的,但这个步骤不是毫无用处的,我们要记住这串网址。
https://video.pearvideo.com/mp4/third/20210508/cont-1728888-11721137-174842-hd.mp4
因为是动态加载的数据,我们可以到 XHR 里面去找网址会不会在这里面。
我们一看,果然在!
不过先别太激动,我们把阿贾克斯加载的网址复制下来,就又发现问题了。
https://video.pearvideo.com/mp4/third/20210508/1620721592006-11721137-174842-hd.mp4
我们两相对比后,发现相差的部分是:“ cont-1728888 ”。那么 count 后面的数字是从什么地方来的呢?
还记得我们一开始爬取的超链接吗?
video_1728888。这里的数字不就是我们要的吗?
欧克,分析了之后,我们还要阿贾克斯加载的参数。
我们发现其中的 contld 是已知的,那么剩下的 mrd 是什么呢?
很简单,什么都不是,只是一串随机数
到这里,我们就完成了对爬取梨视频的分析,剩下的就是代码的问题了。
同步爬虫爬取梨视频
import requests
from lxml import etree
import os
import time
import random
import re
def save_video(videoNum_title):
video_num = videoNum_title[0]
title = videoNum_title[1]
# UA伪装
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
"Referer": "https://www.pearvideo.com/" + "video_" + video_num
}
# 指定url
url = "https://www.pearvideo.com/videoStatus.jsp"
# 传入参数
param = {
"contId": video_num,
"mrd": str(random.random())
}
# 获取假网址
json = requests.get(url = url, headers = header, params = param).json()
href = json["videoInfo"]["videos"]["srcUrl"]
# 获取真正的网址
url = re.sub(r"/.{13}-", "/cont-" + video_num + "-", href)
# 保存视频
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
video = requests.get(url = url, headers =header).content
if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频\\" + title + ".mp4"):
with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频\\" + title + ".mp4", "wb") as fp:
print(title, "正在下载……")
fp.write(video)
print(title, "下载完成!!!")
if __name__ == '__main__':
start = time.time()
# 创建文件夹
if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频"):
os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频")
# UA伪装
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
# 指定 url
url = "https://www.pearvideo.com/category_4"
# 发送请求
page = requests.get(url = url, headers = header).text
# xpath 解析
tree = etree.HTML(page)
li_list = tree.xpath('//*[@id="listvideoListUl"]/li') # li 标签列表
List = []
for li in li_list:
title = li.xpath('div//div[@class="vervideo-title"]/text()')[0].split(" ")[-1]
video_num = li.xpath('div/a/@href')[0][6:]
List.append((video_num, title))
for videoNum_title in List:
save_video(videoNum_title)
end = time.time()
print(end - start)
print("over!!!")
同步用时 45 秒,现在让我们试试异步
异步爬虫爬取梨视频
import requests
from lxml import etree
import os
import time
import random
import re
from multiprocessing import Pool
def save_video(videoNum_title):
video_num = videoNum_title[0]
title = videoNum_title[1]
# UA伪装
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
"Referer": "https://www.pearvideo.com/" + "video_" + video_num
}
# 指定url
url = "https://www.pearvideo.com/videoStatus.jsp"
# 传入参数
param = {
"contId": video_num,
"mrd": str(random.random())
}
# 获取假网址
json = requests.get(url = url, headers = header, params = param).json()
href = json["videoInfo"]["videos"]["srcUrl"]
# 获取真正的网址
url = re.sub(r"/.{13}-", "/cont-" + video_num + "-", href)
# 保存视频
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
video = requests.get(url = url, headers =header).content
if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频\\" + title + ".mp4"):
with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频\\" + title + ".mp4", "wb") as fp:
print(title, "正在下载……")
fp.write(video)
print(title, "下载完成!!!")
if __name__ == '__main__':
start = time.time()
# 创建文件夹
if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频"):
os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频")
# UA伪装
header = {
"user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
# 指定 url
url = "https://www.pearvideo.com/category_4"
# 发送请求
page = requests.get(url = url, headers = header).text
# xpath 解析
tree = etree.HTML(page)
li_list = tree.xpath('//*[@id="listvideoListUl"]/li') # li 标签列表
List = []
for li in li_list:
title = li.xpath('div//div[@class="vervideo-title"]/text()')[0].split(" ")[-1]
video_num = li.xpath('div/a/@href')[0][6:]
List.append((video_num, title))
# 使用线程池
pool = Pool()
pool.map(save_video, List)
pool.close()
pool.join()
end = time.time()
print(end - start)
print("over!!!")