python-(6-6-2)爬虫---协程

本文深入介绍了Python中的阻塞与协程概念,阐述了协程如何解决IO操作导致的阻塞问题。通过两种协程实现方式展示了并发执行任务的效率提升,并给出了下载管理和图片下载的实战案例,强调了异步编程在提高程序性能方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 阻塞和协程

在处理多个任务时,CPU不为当前的任务进行工作,此时就出现了阻塞状态。
一般当程序处于IO操作时,都会出现阻塞,比如input()requests.get(),前者是等待输入数据,后者是等待对面服务器的响应反馈结果。

协程就是当程序遇见了IO操作时,选择性的切换到其他任务上,让CPU不停止工作。
在微观上体现为遇见IO后的一个任务一个任务的切换,多任务异步操作;
在宏观上观察为多个任务是一起执行。

二 协程的两种写法

第一种方法:

import asyncio
import time

async def func1():
    print("你好,我是野比大雄")
    # 异步操作,并挂起,让CPU执行其他任务
    await asyncio.sleep(3)  
    print("你好,我是野比大雄")

async def func2():
    print("你好,我是哆啦A梦")
    await asyncio.sleep(2)
    print("你好,我是哆啦A梦")

async def func3():
    print("你好,我是源静香")
    await asyncio.sleep(4)
    print("你好,我是源静香")

if __name__ == '__main__':
    f1 = func1()
    f2 = func2()
    f3 = func3()
    tasks = [
        f1,f2,f3
    ]
    # 协程前计时
    t1 = time.time()
    # (协程)一次性启动多个任务
    asyncio.run(asyncio.wait(tasks))
    # 任务执行完成后计时
    t2 = time.time()
    # 总共耗时
    print(t2 -t1)

第二种写法:

import asyncio
import time

async def func1():
    print("你好,我是野比大雄")
    await asyncio.sleep(3)
    print("你好,我是野比大雄")

async def func2():
    print("你好,我是哆啦A梦")
    await asyncio.sleep(2)
    print("你好,我是哆啦A梦")

async def func3():
    print("你好,我是源静香")
    await asyncio.sleep(4)
    print("你好,我是源静香")

async def main():
    tasks = [
        func1(),
        func2(),
        func3()
    ]
    await asyncio.wait(tasks)

if __name__ == '__main__':
    # 协程前计时
    t1 = time.time()
    # (协程)一次性启动多个任务
    asyncio.run(main())
    # 任务执行完成后计时
    t2 = time.time()
    # 总共耗时
    print(t2 -t1)

三 协程的简单应用

import asyncio
import time

async def download(url):
    print("准备开始下载。。。")
    # 模拟网络请求
    await asyncio.sleep(3)
    print("下载完毕!!!")

async def main():
    urls = [
        "https://www.bilibili.com/",
        "http://www.baidu.com",
        "https://www.youkuaiyun.com/"
    ]
    tasks = []
    for url in urls:
        d = download(url)
        tasks.append(d)
    await asyncio.wait(tasks)

if __name__ == '__main__':
    # 协程前计时
    t1 = time.time()
    # (协程)一次性启动多个任务
    asyncio.run(main())
    # 任务执行完成后计时
    t2 = time.time()
    # 总共耗时
    print(t2 - t1)

四 实战案例

这一节需要用到一个新的模块,要导入aiohttp模块,必须先安装这个模块。

在这里插入图片描述
安装完成后,会有提示信息。

在这里插入图片描述

在获取相关内容的基本信息后,我们就准备写代码,代码如下:

import asyncio
import aiohttp

urls = [
    "http://kr.shanghai-jiuxin.com/file/bizhi/20220927/ortyhsuzqrb.jpg",
    "http://kr.shanghai-jiuxin.com/file/bizhi/20220927/mow1dr2kbce.jpg",
    "http://kr.shanghai-jiuxin.com/file/bizhi/20220927/ued4qp5cj2x.jpg"
]

async def aiodownload(url):
    # 从右往左切2刀,得到[-1]位置的内容;而split()则从左往右切
    name = url.rsplit("/",2)[-1]
    # 发送requests请求
    async with aiohttp.ClientSession() as session:
        # 等价于 resp = requests.get()
        async with session.get(url) as resp:
            # 得到请求响应,写入文件,创建文件
            with open(name,mode="wb") as f:
                # 读取内容的程序是异步的,需要await挂起
                f.write(await resp.content.read())
    print(name, "下载完成!!!")

async def main():
    tasks = []
    for url in urls:
        tasks.append(aiodownload(url))
    await asyncio.wait(tasks)

if __name__ == '__main__':
    asyncio.run(main())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值