爬虫中使用异步实现高性能的数据爬取操作。
一:多线程,多进程(不建议)
好处:可以为相关阻塞的操作单独开启线程或者进程,祖泽操作就可以异步执行
坏处:无法没有限制的开启多线程或者多进程
二:线程池。进程池(适当的使用):
好处:我们可以降低系统对进程或者线程创建和销毁的一个频率,从而很好的降低系统开销
坏处:线程池中的线程数量是有上限的
三:同步爬取的示例
我之前测试过的代码中就有类似的范例。(同步爬取的范例)
爬取贝壳找房中的图片,代码如下:
import time
import requests
import random
# 导入线程池模块
from multiprocessing.dummy import Pool
# 引入etree模块
from lxml import etree
def getImage(url):
"""
:name 爬取网络图片
:param url: 图片url
:return: 无返回值
"""
# 1:指定url
# url = "https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg"
# 2:模拟网络请求链接
responce = requests.get(url=url)
# 3:获取响应数据,content获取二进制数据
content = responce.content
strs = ''.join(random.sample(['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'], 5))
filename = './img/'+ strs +'.jpg'
# 4:持久化存储
with open(filename, 'wb') as fe:
fe.write(content)
print('爬取完成'+str(time.time()))
# 加载线上html
# 1:指定url
url = "https://dl.ke.com/ershoufang/"
# 2:UA伪装 将对应的User-Agent封装到一个字典中(浏览器标识去浏览器中用f12查看源代码获取就好了)
headers = {
"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43'
}
# 3:模拟网络请求链接
responce = requests.get(url=url, headers=headers)
# 4:获取响应数据
content = responce.text
# 5 :xpath 解析
tree = etree.HTML(content)
# 6:解析标签,获取数据
html = tree.xpath('//img[@class="lj-lazy"]/@data-original')
for item in html:
getImage(item)
print(html)
上边的代码中,每爬取完成一张图片,我都会输出一个“爬取完成”
程序输出结果如下图所示:
后边链接的是爬取成功之后的时间戳,我们可以看到,时间戳是从上到下依次增长的。说明这个爬取图片是同步进行的。
四:异步爬取的示例
我这里对上边的程序进行一个修改:只需要将for循环调用获取图片的函数那个位置改为有线程池执行即可。
修改完成代码如下:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2022/3/9 19:48
# @Author : camellia
# @Email : 805795955@qq.com
# @File : threadpool.py
# @Software: PyCharm
import time
import requests
import random
# 导入线程池模块
from multiprocessing.dummy import Pool
# 引入etree模块
from lxml import etree
def getImage(url):
"""
:name 爬取网络图片
:param url: 图片url
:return: 无返回值
"""
# 1:指定url
# url = "https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg"
# 2:模拟网络请求链接
responce = requests.get(url=url)
# 3:获取响应数据,content获取二进制数据
content = responce.content
strs = ''.join(random.sample(['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'], 5))
filename = './img/'+ strs +'.jpg'
# 4:持久化存储
with open(filename, 'wb') as fe:
fe.write(content)
print('爬取完成'+str(time.time()))
# 加载线上html
# 1:指定url
url = "https://dl.ke.com/ershoufang/"
# 2:UA伪装 将对应的User-Agent封装到一个字典中(浏览器标识去浏览器中用f12查看源代码获取就好了)
headers = {
"User-Agent":'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36 Edg/98.0.1108.43'
}
# 3:模拟网络请求链接
responce = requests.get(url=url, headers=headers)
# 4:获取响应数据
content = responce.text
# 5 :xpath 解析
tree = etree.HTML(content)
# 6:解析标签,获取数据
html = tree.xpath('//img[@class="lj-lazy"]/@data-original')
# ##########################################################
# 使用线程池爬取数据
# 实例化一个线程池对象
pool = Pool(len(html))
# 传入需要调用的方法 图片列表
pool.map(getImage,html)
# ##########################################################
# 同步爬取数据
# for item in html:
# getImage(item)
# print(html)
输出结果如下图所示:
通过上图标红框的位置我们可以看到,其爬取完成的时间相同,这就说明是异步多线程进行爬取的。
以上大概就是 python 线程池的 基本使用。
有好的建议,请在下方输入你的评论。