Python提供了一些强大的异步框架,帮助我们处理并发任务,提高程序运行效率。我们接下来将主要介绍两个框架:asyncio
和aiohttp
。
1. asyncio
asyncio
是Python标准库中的一个用于编写单线程并发代码的模块,使用事件循环驱动的协程。它允许我们使用async/await
语法编写并发代码。
基本使用
我们可以通过以下代码来创建一个简单的异步任务:
import asyncio
async def hello():
print('Hello World')
loop = asyncio.get_event_loop()
task = loop.create_task(hello())
loop.run_until_complete(task)
在上面的例子中,我们首先定义了一个异步函数hello
,然后通过loop.create_task
方法创建了一个任务,最后用loop.run_until_complete
方法来运行这个任务。
并发运行
在进行网络爬虫时,我们可以用asyncio
并发地运行多个网络请求,提高爬虫的效率:
import asyncio
async def fetch_url(url):
print(f'Start fetching {url}')
await asyncio.sleep(2) # 模拟网络请求
print(f'Finish fetching {url}')
urls = ['url1', 'url2', 'url3']
loop = asyncio.get_event_loop()
tasks = [loop.create_task(fetch_url(url)) for url in urls]
loop.run_until_complete(asyncio.wait(tasks))
2. aiohttp
虽然asyncio
提供了异步I/O的基本功能,但它并没有提供进行HTTP请求的工具。这就是aiohttp
库的作用。
基本使用
以下是一个基本的aiohttp
请求示例:
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
html = await fetch(session, 'http://python.org')
print(html)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
在上面的例子中,我们首先创建了一个ClientSession
对象,然后用这个对象的get
方法发起了一个GET请求,最后用response.text()
方法获取了响应的文本内容。
并发请求
在进行网络爬虫时,我们可以用aiohttp
和asyncio
一起并发地运行多个HTTP请求,提高爬虫的效率:
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = ['http://python.org', 'http://www.google.com', 'http://www.apple.com']
tasks = []
async with aiohttp.ClientSession() as session:
for url in urls:
task = fetch(session, url)
tasks.append(task)
htmls = await asyncio.gather(*tasks)
for url, html in zip(urls, htmls):
print(url, len(html))
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
在上面的例子中,我们用了asyncio.gather
函数来并发地运行多个fetch
任务,并通过zip
函数来将每个URL与其对应的HTML内容打印出来。
推荐阅读:
https://mp.weixin.qq.com/s/dV2JzXfgjDdCmWRmE0glDA
https://mp.weixin.qq.com/s/an83QZOWXHqll3SGPYTL5g
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。