共计 2359 个字符,预计需要花费 6 分钟才能阅读完成。
在上一节我们学习了协程的基本概念以及 async/await 的使用方式。本篇我们将进一步深入异步编程的实战部分,重点讲解如何利用 aiohttp 来实现高并发网络请求,这在爬虫、API 调用、分布式任务中极其重要。
一、为什么使用 aiohttp?
Python 标准库的 asyncio 并不能直接发送 HTTP 请求,而 aiohttp 正是为异步网络 I/O 而生的库。
相比传统同步方式(如 requests):
- 同步:一次只能等待一个请求返回
- 异步:同时发起多个请求,用事件循环调度等待
这使得 aiohttp 在高并发访问场景下性能优势极大。
二、安装 aiohttp
如果你尚未安装,请使用:
pip install aiohttp
三、使用 aiohttp 发送异步请求
下面是最基本的 GET 请求示例:
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()
async def main():
url = "https://www.python.org/"
content = await fetch(url)
print(content[:200])
asyncio.run(main())
要点解析:
- ClientSession:用于管理连接池,提高性能
- await resp.text():异步读取内容
- async with:确保连接自动关闭,避免资源泄露
四、并发请求:批量抓取多个网页
高并发的精髓在于 asyncio.gather:
import aiohttp
import asyncio
async def fetch(url, session):
async with session.get(url) as resp:
text = await resp.text()
print(f"{url} 获取成功 ")
return text
async def main():
urls = [
"https://www.python.org/",
"https://www.github.com/",
"https://www.wikipedia.org/",
"https://www.qq.com/",
"https://www.bing.com/"
]
async with aiohttp.ClientSession() as session:
tasks = [fetch(url, session) for url in urls]
results = await asyncio.gather(*tasks)
asyncio.run(main())
优点:
- 所有请求并发执行
- 性能远超同步代码
- 对 I/O 密集任务效率提升显著
五、限制并发数量(避免压力过大)
过高的并发可能压垮网站或自己的网络,需要设置 Semaphore:
import aiohttp
import asyncio
sem = asyncio.Semaphore(5) # 最多 5 个并发
async def fetch(url, session):
async with sem:
async with session.get(url) as resp:
print(f" 抓取:{url}")
return await resp.text()
async def main():
urls = [... 同上...]
async with aiohttp.ClientSession() as session:
tasks = [fetch(url, session) for url in urls]
await asyncio.gather(*tasks)
asyncio.run(main())
这样可以有效控制请求数量,避免触发网站的反爬机制。
六、异常处理:防止程序中断
加入 try/except 捕获异常并继续执行:
async def fetch(url, session):
try:
async with session.get(url, timeout=5) as resp:
return await resp.text()
except Exception as e:
print(f" 请求失败:{url},原因:{e}")
return None
七、实战案例:批量爬取网页标题
示例解析网页标题 <title>:
import aiohttp
import asyncio
import re
async def fetch_title(url, session):
try:
async with session.get(url) as resp:
text = await resp.text()
title = re.search(r"<title>(.*?)</title>", text, re.S)
print(f"{url} 标题:{title.group(1) if title else ' 未找到 '}")
except:
print(f"{url} 获取失败 ")
async def main():
urls = [
"https://www.python.org/",
"https://www.github.com/",
"https://www.bilibili.com/"
]
async with aiohttp.ClientSession() as session:
await asyncio.gather(*(fetch_title(url, session) for url in urls))
asyncio.run(main())
八、小结
在本篇中你学习了:
- aiohttp 的基本使用方式
- 如何进行异步并发请求
- 如何限制并发数量
- 如何处理异常
- 如何编写实战爬虫应用
异步 I/O 是 Python 现代工程中非常重要的一环,掌握 aiohttp 能显著提升你的程序性能。
如果你需要继续下一篇(Day120),告诉我即可。
正文完