一起学爬虫(Python) — 11
概念
- event_loop:事件循环,也就是通过不断的循环获取任务的状态(完成/未完成)来分配任务。
- coroutine:协程对象,python中万物皆对象,不多说,懂的都懂。
- task:任务对象,对协程对象进行包装,加上了状态,完成和未完成。
- future:和task一样,只不过可以提前包装。
- async:定义一个协程,定义!
- await:挂起阻塞的操作,还记得之前说的IO等待吗,在那前面就要用到这个。
第一个案例
第一步,导入我们的asyncio模块,async+io!!!
第二步,用async定义一个协程,定义!
记住用await挂起阻塞的操作,也就是asyncio.sleep(2),这里是为了模拟下载所需要花费的时间!
awa
第三步,创建一个协程对象,对象,懂的都懂!
第四步,用event_loop创建一个事件循环,也就是游戏里的任务公布栏之类的~
第五步,是不是觉得该把任务对象方法事件循环中了??还真是的!
然后执行,就会成功执行我们的async函数:
第二个案例
那么这个时候就要有人问了,刚开始说的1,2,5,6都用上了,那3,4呢,3,4呢,3,4呢……
这就给大家用上!
task
-
这里我们就把duixiang这个协程对象放置到task任务对象,然后再把task任务对象放到任务列表中:
那么到这里就有人问了,用task和不用task又没有区别,为什么要用task呢?
我们来打印一下任务完成前后的task!
看到没有!!task给每个任务都贴上了标签,让循环器更好的去筛选哪些是完成了的,哪些是没完成的!
future也是一样的,这里就不多说了,我们主要用task。
实现异步下载图片
昨天呢,我们本来是要用异步实现下载图片的,但是遇到了一个小问题,那就是requests模块它不支持异步,那我们也没有办法强人锁男的啦,人各有志,让我们工地见面。
好啦,教大家一个支持异步的同时也支持requests功能的新模块!
aiohttp aiohttp aiohttp aiohttp aiohttp ……
aiohttp
首先,环境安装!
pip install aiohttp
当然你也可以在pycharm里直接搜索安装模块!
安装完了这个模块之后呢,先不要急,先想一个问题:
我们既然有了进程池,又有了异步,是不是可以把他们结合起来呢?是的!!
所以就有一个东西,叫做多线程异步协程。也就是说每个线程里的程序都能进行异步!!! 如果还是听不懂的话…那就照着用,毕竟用起来也是不难的,因为异步协程这一部分知识呢,是属于基础进阶那一块的,想要详细说又要花很多篇幅,如果你实在是想学,或者实在是对基础不太熟练,那就留个言,如果反映人数够多的话,小泽就专门开一个基础的坑,带大家一起学python的基础!
但是先告诉大家有这个东西,今天呢,我们还是只来实现多任务异步协程,而不是多线程异步协程!
整体的思路流程
我们已经有了aiohttp,心里就会很踏实也很安心,所以先按照流程来,这次跟着小泽的思路走:
第一步,我们先写一个下载图片的函数:
# 定义一个函数,需要传入url参数
def func(url):
# UA伪装
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
# 向图片的网址发起请求,获取二进制数据
response = requests.get(url=url,headers=headers).content
# 用上下文管理器保存
name = url.split('/')[-1]
with open(name,'wb') as fp:
fp.write(response)
路人:你明明说了requests不能用,你还用,你是不是傻!
害,这里不就是用一下嘛,方便我们思路的继续进行,听懂掌声~
第二步,找到我们的三张图片,如果你比较懒,你肯定很懒,那就用小泽给大家准备的三张图片好了:
urls = ['https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_01.png',
'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_02.png',
'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_03.png'
]
放心,不是什么美女 美丽的图片,只是一些正常的图片~
第三步,建立一个循环,把urls里的url依次放入函数中……
等等!这样不就成了同步的操作,说好的多任务异步协程呢!
所以真正的第三步是用循环把所有任务都封装起来:
# 建立任务列表
tasks = []
# 遍历出每一个url
for url in urls:
# 协程对象
a = func(url)
# 封装
task = asyncio.ensure_future(a)
# 把封装好的任务加到任务列表里
tasks.append(task)
当然,也不要忘了给我们的函数,加上async,这样才能让系统知道这个函数是个协程函数!
然后接下来,就是建立事件循环,再把我们的任务列表放进事件循环中!
# 建立事件循环
loop = asyncio.get_event_loop()
# 把任务列表放到事件循环中
loop.run_until_complete(asyncio.wait(tasks))
因为是任务列表,而不是单个任务,所以前面要加上asyncio.wait() 不加的统统拉出去,这么嚣张还想开军舰!
好的,整段写完,剩下的唯一一个问题就是requests模块的问题啦,现在我们就开始说,到底要怎么用aiohttp~
直接上代码!
async def func(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
# 方便我们直观看到异步的效果
print('开始下载',url)
# 类似于上下文管理器,就是with open,with前面一定要加async,固定写法
# as session是类似起名字一样
async with aiohttp.ClientSession() as session:
# async with跟上面同理,await是手动挂起,因为向图片发起请求是IO操作
async with await session.get(url=url,headers=headers) as response:
# 同样的,对返回的数据进行解析也是IO操作
# 不同于requests模块,read()指的是解析二进制数据
# text() 就是我们平时用的text
# 而json对象则要用json()
data = await response.read()
# 对url最后的部分进行截取
name = url.split('/')[-1]
with open(name,'wb') as fp:
fp.write(data)
print('下载完成',url)
我们只需要把func这个协程对象,改成如上所述的内容就可以啦!
至于为什么呢,用法就是上面那样用的,如果看代码看不懂的话…可能是前面几章你没有好好看,当然如果真的真的看不懂,不要怕,先能看懂多少看懂多少,更详细的我们之后再说,在评论区留下你的疑惑和想跟小泽说的话,么么哒~
然后直接运行,揍你!
看着下载效率,多棒啊,我好了,你们呢~
关于多任务异步协程呢,就先到这里了,更详细的要放到不知道哪一篇讲了,因为很多小伙伴在催着要讲模拟登陆这一块了……
很黄很暴力
没广告,没卖课,只有一群爱学习的小伙伴,如果你基础薄弱,或者想搞些大的,欢迎加进来!!!
小泽爱你们,(づ ̄ 3 ̄)づ
本文地址:https://blog.csdn.net/BcXbHello/article/details/110873328