本文章所涉及的案例仅供学习研究,如若侵犯到贵公司权益请联系2328409226@qq.com
第一时间进行删除;各位朋友切忌用于一切非法途径,否则后果自行承担!
文章目录
文章知识点
- 单线程、多线程
- 线程池
- 单协程、多协程
- headers中Refere的作用
- 异步模块aiohttp使用
本章节学习内容来自Python爬虫7天速成(2020全新合集)无私分享 Python
一、异步爬虫概述
高性能异步爬虫 :在爬虫中使用异步实现高性能的数据爬取操作
传统爬取数据的操作是顺序操作,下面看一个实例
- 代码
分析上述代码可知 for循环中的get方法会阻塞程序,只有请求到的数据获取后,才可以进行下一条url中对应的数据
上述可知,使用异步会提高爬虫程序的数据获取效率
- 异步爬虫的方式
- 多线程,多进程
好处:可以为相关阻塞的操作单独开启线程或进程,阻塞操作就可以异步进行
弊端:无法无限制的开启多线程或者多进程- 线程池、进程池(适当的使用)
好处:我们可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统的开销
弊端:池中线程或进程的数量是有上限的。
二、线程池的基本使用
- 单线程串行方式使用
import time
# 单线程串行方式运行
def get_page(str):
print("正在下载:",str)
time.sleep(2)
print("下载成功:",str)
name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
for i in range(len(name_list)):
get_page(name_list[i])
end_time = time.time()
print('%d second' % (end_time - start_time))
- 线程池的使用
import time
# 导入线程池模块对应的类
from multiprocessing.dummy import Pool
# 使用线程池方式执行
# Pool一定是应用在阻塞操作中的 get_page
start_time = time.time()
def get_page(str):
print("正在下载:",str)
time.sleep(2)
print("下载成功:",str)
name_list = ['xiaozi','aa','bb','cc']
# 实例化一个线程池对象
pool = Pool(4) # 4个线程对象
# 将列表中每一个列表元素传递给get_page进行处理
# pool.map的返回值就是方法get_page()的返回值
pool.map(get_page,name_list)
end_time = time.time()
print(end_time-start_time)
三、异步爬取线程池案例使用⭐⭐
本案例仅供学习研究,如若侵犯到贵公司权益请联系2328409226@qq.com
第一时间进行删除;各位朋友切忌用于一切非法途径,否则后果自行承担!
以上视频是我们需要爬取的具体视频,键盘上F12查看并且分析相关的detail_url和name,
- 信息分析
到此你可能认为使用xpath进行地址获取下载即可,但是这样就错了,你使用etree进行解析出来的是空值,因为这个页面的有些数据就是动态加载出来的,如下进行验证:
到此为止,我们发现数据是动态加载出来的,因此我们就需要找出真正要下载的地址链接在哪里?
在此感谢这两位博主提供的思路:
- 地址信息对比
- 报错404:
https://video.pearvideo.com/mp4/adshort/20210927/1632790695959
-15774345_adpkg-ad_hd.mp4- 正确的路径:
https://video.pearvideo.com/mp4/adshort/20210927/cont-1742572
-15774345_adpkg-ad_hd.mp4
此外多次实验发现获取报错404地址的网址有一部分数字是随机产生的,
- 真实信息地址
- 宝藏老师|数学老师的浪漫:用函数讲述自己的爱情故事:
https://www.pearvideo.com/videoStatus.jsp?contId=1742617
&mrd=0.6446715186101781- 小伙肿瘤医院旁开共享厨房,宣传5元吃饱亏本运营:
https://www.pearvideo.com/videoStatus.jsp?contId=1742572
&mrd=0.5091336020577668
通过以上两个视频的地址不难发现它们网址都有共同的特点包含contId,我们再回到原始的视频网页数据查看:
后来由于个人水平问题这个属性值解析出错,因此换了思路:
- 解析地址
https://www.pearvideo.com/videoStatus.jsp?contId=1742572&mrd=0.8749545784196235
https://www.pearvideo.com/videoStatus.jsp?contId=1742572&mrd=0.5510063831062151
https://www.pearvideo.com/videoStatus.jsp?contId=1742572&mrd=0.5091336020577668
3.1 代码
- 源代码
import requests
from lxml import etree
import random
import json
from multiprocessing.dummy import Pool
# 需求:安去li视频的视频数据
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36'
}
# 原则:线程池处理的是阻塞且耗时的操作
# 对下述url发起请求解析出视频详情页的url和视频的名称
url = "https://www.pearvideo.com/"
page_text = requests.get(url=url, headers=headers).text
tree = etree.HTML(page_text)
# xpath返回的是列表 ['video_1742557']
all_addresses = tree.xpath("//div[@id='vervideoTlist']//a[@class='vervideo-lilink actplay']/@href")
# print(all_addresses)
# ['video_1742557', 'video_1742534', 'video_1742545', 'video_1733739', 'video_1718659']
all_names = tree.xpath('//div[@id="vervideoTlist"]//div[@class="vervideo-name"]/text()')
# print(all_names)
urls = []
for i in range(len(all_addresses)):
video_url = 'https://www.pearvideo.com/' + all_addresses[i]
mp4_name