欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一起学爬虫(Python) — 11

程序员文章站 2022-03-15 15:04:02
今天我们学异步协程概念第一个案例第二个案例实现异步下载图片整体的思路流程很黄很暴力概念event_loop:事件循环,也就是通过不断的循环获取任务的状态(完成/未完成)来分配任务。coroutine:协程对象,python中万物皆对象,不多说,懂的都懂。task:任务对象,对协程对象进行包装,加上了状态,完成和未完成。future:和task一样,只不过可以提前包装。async:定义一个协程,定义!await:挂起阻塞的操作,还记得之前说的IO等待吗,在那前面就要用到这个。第一个案例第...

概念

  1. event_loop:事件循环,也就是通过不断的循环获取任务的状态(完成/未完成)来分配任务。
  2. coroutine:协程对象,python中万物皆对象,不多说,懂的都懂。
  3. task:任务对象,对协程对象进行包装,加上了状态,完成和未完成。
  4. future:和task一样,只不过可以提前包装。
  5. async:定义一个协程,定义!
  6. await:挂起阻塞的操作,还记得之前说的IO等待吗,在那前面就要用到这个。

第一个案例

第一步,导入我们的asyncio模块,async+io!!!
一起学爬虫(Python) — 11
第二步,用async定义一个协程,定义!
一起学爬虫(Python) — 11
记住用await挂起阻塞的操作,也就是asyncio.sleep(2),这里是为了模拟下载所需要花费的时间!

awa

第三步,创建一个协程对象,对象,懂的都懂!
一起学爬虫(Python) — 11

第四步,用event_loop创建一个事件循环,也就是游戏里的任务公布栏之类的~
一起学爬虫(Python) — 11
第五步,是不是觉得该把任务对象方法事件循环中了??还真是的!
一起学爬虫(Python) — 11

然后执行,就会成功执行我们的async函数:
一起学爬虫(Python) — 11

第二个案例

那么这个时候就要有人问了,刚开始说的1,2,5,6都用上了,那3,4呢,3,4呢,3,4呢……
这就给大家用上!
task

  • 一起学爬虫(Python) — 11
    这里我们就把duixiang这个协程对象放置到task任务对象,然后再把task任务对象放到任务列表中:
    一起学爬虫(Python) — 11
    那么到这里就有人问了,用task和不用task又没有区别,为什么要用task呢?

我们来打印一下任务完成前后的task!

一起学爬虫(Python) — 11

看到没有!!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,这样才能让系统知道这个函数是个协程函数!

一起学爬虫(Python) — 11
然后接下来,就是建立事件循环,再把我们的任务列表放进事件循环中!

# 建立事件循环
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这个协程对象,改成如上所述的内容就可以啦!

至于为什么呢,用法就是上面那样用的,如果看代码看不懂的话…可能是前面几章你没有好好看,当然如果真的真的看不懂,不要怕,先能看懂多少看懂多少,更详细的我们之后再说,在评论区留下你的疑惑和想跟小泽说的话,么么哒~

然后直接运行,揍你!

一起学爬虫(Python) — 11
看着下载效率,多棒啊,我好了,你们呢~

关于多任务异步协程呢,就先到这里了,更详细的要放到不知道哪一篇讲了,因为很多小伙伴在催着要讲模拟登陆这一块了……

很黄很暴力

一起学爬虫(Python) — 11
没广告,没卖课,只有一群爱学习的小伙伴,如果你基础薄弱,或者想搞些大的,欢迎加进来!!!

小泽爱你们,(づ ̄ 3 ̄)づ

本文地址:https://blog.csdn.net/BcXbHello/article/details/110873328

相关标签: 爬虫 python