python并发编程:Python异步IO实现并发爬虫

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
大数据开发治理平台 DataWorks,不限时长
实时数仓Hologres,5000CU*H 100GB 3个月
简介: python并发编程:Python异步IO实现并发爬虫

往期文章:

  1. 并发编程简介
  2. 怎样选择多线程多进程多协程
  3. Python速度慢的罪魁祸首,全局解释器锁GIL
  4. 使用多线程,Python爬虫被加速10倍
  5. Python实现生产者消费者爬虫
  6. Python线程安全问题以及解决方案
  7. Python好用的线程池ThreadPoolExecutor
  8. Python使用线程池在Web服务中实现加速
  9. 使用多进程multiprocessing模块加速程序的运行
  10. 使用多进程multiprocessing模块加速程序的运行

协程内容的介绍

  • 上图的上面是单线程爬虫 cpu的执行情况,可以发现,经常因为等待IO而影响CPU的执行效率。
  • 上图的下面是协程,协程主要是在单线程内实现的,以爬虫为例,协程先是让cpu爬取第一个url的内容,等待IO的时候,它又让CPU爬取第二个url的内容,当第二个任务等待IO的时候,它又让CPU爬取第三个url的内容,然后第三个任务等待IO, 它又循环回来,执行第一个任务,就这样返回循环。 所以,协程就是大循环。

asyncio使用

import asyncio

# 获取事件循环
loop = asyncio.get_event_loop()

# 定义协程
async def myfunc(url):
    await get_url(url)

# 创建task列表
tasks = [loop.create_task(myfunc(url)) for url in urls]

# 执行爬虫事件列表
loop.run_until_complete(asyncio.wait(tasks))

注意:

  • 要用在异步IO编程中, 依赖的库必须支持异步IO特性
  • 爬虫引用中:requests 不支持异步, 需要用 aiohttp

代码演示

import aiohttp
import asyncio
from loguru import logger
from  cnblogs_spider import urls
import time

async def async_craw(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            result = await resp.text()
            logger.info("craw url {},{}".format(url,len(result)))


loop = asyncio.get_event_loop()
# 定义超级循环
tasks = [ loop.create_task(async_craw(url))  for url in urls]


start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
logger.info("use time {}秒".format(end-start))

执行结果如下:

信号量

信号量(英语:Semaphore)又称为信号量、旗语是一个同步对象,用于保持在0至指定最大值之间的一个计数值。

  • 当线程完成一次对该semaphore对象的等待(wait)时,该计数值减一;
  • 当线程完成一次对semaphore对象的释放(release)时,计数值加一。
  • 当计数值为0,则线程等待该semaphore对象不再能成功直至该semaphore对象变成signaled状态
  • semaphore对象的计数值大于0,为signaled状态;计数值等于0,为nonsignaled状态.

信号量是用来控制并发度的。

主要有两种实现方式:

  • 方式一:
    ```python
    sem = asyncio.Semaphore(10)

... later

async with sem:

# work with shared resource

- 方式二:
```python
sem = asyncio.Semaphore(10)

# ... later
await sem.acquire()
try:
    # work with shared resource
finally:
    sem.release()

用信号量控制协程数进行爬虫

import aiohttp
import asyncio
from loguru import logger
from  cnblogs_spider import urls
import time



# 加入信号量,控制并发度
semaphore = asyncio.Semaphore(10)

async def async_craw(url):
    async with semaphore:
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                result = await resp.text()
                logger.info("craw url {},{}".format(url,len(result)))


loop = asyncio.get_event_loop()
# 定义超级循环
tasks = [ loop.create_task(async_craw(url))  for url in urls]


start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
logger.info("use time {}秒".format(end-start))

总结

本系列的文章已经更新完毕,如果大家对python并发编程感兴趣的可以关注攻城狮成长日记公众号,获取更多的内容,以下是本系列的全部代码。大家可以访问这个网址获取代码https://gitee.com/didiplus/pythonscript.git

目录
相关文章
|
6天前
|
安全 数据安全/隐私保护 数据中心
Python并发编程大挑战:线程安全VS进程隔离,你的选择影响深远!
【7月更文挑战第9天】Python并发:线程共享内存,高效但需处理线程安全(GIL限制并发),适合IO密集型;进程独立内存,安全但通信复杂,适合CPU密集型。使用`threading.Lock`保证线程安全,`multiprocessing.Queue`实现进程间通信。选择取决于任务性质和性能需求。
19 1
|
4天前
|
数据采集 数据库 Python
Python并发编程新篇章:asyncio库使用全攻略,轻松驾驭异步世界!
【7月更文挑战第11天】Python的asyncio开启异步编程时代,通过案例展示如何用它和aiohttp构建并发爬虫。安装aiohttp后,定义异步函数`fetch`进行HTTP请求,返回状态码和内容长度。在`main`中,并发执行多个`fetch`任务,利用`asyncio.gather`收集结果。使用`async with`管理HTTP会话资源,确保释放。通过这种方式,爬虫性能大幅提升,适用于高并发场景。学习asyncio是提升并发性能的关键。
28 14
|
1天前
|
消息中间件 安全 数据处理
Python中的并发编程:理解多线程与多进程的区别与应用
在Python编程中,理解并发编程是提高程序性能和响应速度的关键。本文将深入探讨多线程和多进程的区别、适用场景及实际应用,帮助开发者更好地利用Python进行并发编程。
|
4天前
|
调度 开发者 C++
异步风暴来袭!Python asyncio库详解,让你的应用性能飙升!
【7月更文挑战第11天】在高并发时代,Python的asyncio库带来了革命性的异步编程,缓解了GIL和同步IO的性能瓶颈。asyncio基于事件循环和协程实现非阻塞IO,提高资源利用率。对比同步HTTP请求(使用requests)与异步请求(aiohttp+asyncio),后者通过并发减少总耗时,提升了效率。尽管异步编程增加了复杂性,但其优势在于更高的吞吐量和更低延迟。掌握asyncio是现代Python开发的关键,助力构建高性能应用。
|
5天前
|
API 开发者 Python
Python并发新纪元:asyncio库,让你的代码异步飞行,效率翻倍!
【7月更文挑战第10天】Python的asyncio库推动了异步编程革命,简化并发任务,提高I/O效率。通过事件循环和协程,asyncio允许程序在等待如HTTP请求时执行其他任务。例如,使用aiohttp并发获取多个网站数据,显著提升效率。随着asyncio生态成熟,它成为高效编程的必备工具,赋能开发者实现代码的“异步飞行”。
13 2
|
5天前
|
数据库 数据安全/隐私保护 C++
Python并发编程实战:线程(threading)VS进程(multiprocessing),谁才是并发之王?
【7月更文挑战第10天】Python并发对比:线程轻量级,适合I/O密集型任务,但受GIL限制;进程绕过GIL,擅CPU密集型,但通信成本高。选择取决于应用场景,线程利于数据共享,进程利于多核利用。并发无“王者”,灵活运用方为上策。
|
6天前
|
安全 API 调度
深度剖析:Python并发编程中的线程与进程,那些你不可不知的使用技巧与限制!
【7月更文挑战第9天】Python并发:线程适合IO密集型任务,利用GIL下的多线程同步,如示例中使用锁。进程适用于CPU密集型,通过multiprocessing模块实现多进程,利用进程间通信如队列。线程受限于GIL,进程间通信成本高。选择取决于任务需求和性能目标。
12 2
|
1天前
|
存储 调度 Python
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。
异步编程概述在 Python中,`asyncio`库提供了对异步I/O、事件循环、协程(coroutine)和任务的支持。
5 0
|
5天前
|
数据采集 数据库连接 调度
从菜鸟到大师:掌握Python asyncio库,并发编程不再是梦!
【7月更文挑战第10天】Python的asyncio库简化了异步编程,通过事件循环和协程实现非阻塞I/O,提升效率。从`async def`定义异步函数到`await`等待操作,如在`main`函数中并发调用`say_hello`。深入学习涉及自定义协程、异步上下文管理器和信号量。结合如aiohttp,能构建高性能并发应用,实现高效的Web服务。开始你的asyncio之旅,成为并发编程专家!**
11 0
|
5天前
|
Python Windows
从菜鸟到大神:一篇文章带你彻底搞懂Python并发编程——线程篇与进程篇的深度较量!
【7月更文挑战第10天】Python并发编程对比线程与进程。线程适合IO密集型任务,利用`threading`模块,但GIL限制CPU并行。进程适用于CPU密集型任务,通过`multiprocessing`实现,独立内存空间,启动成本高。例子展示了如何创建和管理线程与进程以提高效率。选择取决于任务类型和资源需求。
14 0