0
点赞
收藏
分享

微信扫一扫

(P11-P12)协程,通过信号量控制并发度


文章目录

  • ​​1.协程:在单线程内实现并发​​
  • ​​2.通过信号量控制并发度​​

1.协程:在单线程内实现并发

  • 单线程爬虫的执行路径
  • 协程:在单线程内实现并发
    核心原理:用一个超级循环(其实就是while true)循环
    核心原理:配合IO多路复用原理(IO时CPU可以干其他事情),等待IO时,切换到下一个
    CPU
  • Python 异步IO库介绍:asyncio
    注意:
    (1)要用在异步IO编程中
    依赖的库必须支持异步IO特性
    (2)爬虫引用中:
    requests 不支持异步
    需要用 aiohttp

import asyncio

# 获取事件循环
loop = asyncio.get_event_loop()##就是 while True:

# 定义协程
async def myfunc(url):
await get_url(url)## await目的是IO不进行阻塞,而是让程序进行
下一个loop

# 创建task列表
##对多个url进行并发执行
tasks = [loop.create_task(myfunc(url)) for url in urls]

# 执行爬虫事件列表
loop.run_until_complete(asyncio.wait(tasks))##执行tasks,等待tasks完成

  • eg:08. async_spider.py

import asyncio
import aiohttp
import blog_spider

##协程:在超级循环里可以跑的函数,就是在异步IO中执行async_craw函数
async def async_craw(url):
print("craw url: ", url)
##async with创建对象
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
##resp.text()获取结果
result = await resp.text()
print(f"craw url: {url}, {len(result)}")

##超级循环
loop = asyncio.get_event_loop()

##使用协程函数定义一个list
tasks = [
loop.create_task(async_craw(url))
for url in blog_spider.urls]

import time

start = time.time()
##等待tasks完成
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("use time seconds: ", end - start)

  • 测试:

2.通过信号量控制并发度

  • 信号量(英语:Semaphore)
    信号量(英语:Semaphore)又称为信号量、旗语
    是一个同步对象,用于保持在0至指定最大值之间的一个计数值。
    当线程完成一次对该semaphore对象的等待(wait)时,该计数值减一;
    当线程完成一次对semaphore对象的释放(release)时,计数值加一。
    当计数值为0,则线程等待该semaphore对象不再能成功直至该semaphore对象变成signaled状态
    semaphore对象的计数值大于0,为signaled状态;计数值等于0,为nonsignaled状态.
  • 语法

方法1:
##10就是并发量的意思
sem = asyncio.Semaphore(10)

# ... later
async with sem:
# work with shared resource

方法2:
sem = asyncio.Semaphore(10)

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

  • eg:

import asyncio
import aiohttp
import blog_spider

##并发度10
semaphore = asyncio.Semaphore(10)


async def async_craw(url):
async with semaphore:
print("craw url: ", url)
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
result = await resp.text()
await asyncio.sleep(5)
print(f"craw url: {url}, {len(result)}")


loop = asyncio.get_event_loop()

tasks = [
loop.create_task(async_craw(url))
for url in blog_spider.urls]

import time

start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("use time seconds: ", end - start)

  • 测试:10个10个进行爬取
  • (P11-P12)协程,通过信号量控制并发度_信号量

  • 参考:​​链接​​


举报

相关推荐

0 条评论