Python 异步网络:aiohttp 与异步爬虫
·
Python 异步网络:aiohttp 与异步爬虫
异步网络编程能显著提升I/O密集型任务的效率。aiohttp 是基于 asyncio 的异步HTTP框架,特别适合构建高性能网络应用。以下是核心概念与实践指南:
一、aiohttp 基础
-
核心组件
- 客户端:发送异步HTTP请求
- 服务端:构建异步Web服务
- 关键对象:
ClientSession管理连接池
-
基本请求模板
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session: # 自动管理会话
async with session.get(url) as response:
return await response.text()
async def main():
html = await fetch("https://example.com")
print(html[:200]) # 输出前200字符
asyncio.run(main())
二、异步爬虫设计要点
- 并发控制
使用信号量限制并发数:
semaphore = asyncio.Semaphore(10) # 最大10并发
async def safe_fetch(url):
async with semaphore: # 限制并发
return await fetch(url)
- 任务调度
批量创建任务并收集结果:
urls = [f"https://example.com/page/{i}" for i in range(1,50)]
tasks = [safe_fetch(url) for url in urls]
results = await asyncio.gather(*tasks) # 并行执行
- 错误处理
添加重试机制:
async def robust_fetch(url, retries=3):
for _ in range(retries):
try:
return await safe_fetch(url)
except (aiohttp.ClientError, asyncio.TimeoutError):
await asyncio.sleep(1) # 指数退避更佳
return None
三、性能优化策略
-
连接复用
- 保持
ClientSession单例 - 设置连接池大小:
connector = aiohttp.TCPConnector(limit=100) # 最大连接数 async with aiohttp.ClientSession(connector=connector) as session:
- 保持
-
超时控制
避免阻塞:
timeout = aiohttp.ClientTimeout(total=10) # 10秒总超时
async with session.get(url, timeout=timeout) as response:
- 数据解析
结合异步解析库:aiofiles:异步文件操作BeautifulSoup:在异步上下文中使用同步解析
四、实战案例:异步爬虫
import aiohttp
import asyncio
from bs4 import BeautifulSoup
async def scrape_page(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
html = await resp.text()
soup = BeautifulSoup(html, 'lxml')
title = soup.title.text
return {"url": url, "title": title}
async def main():
urls = [...] # 目标URL列表
tasks = [scrape_page(url) for url in urls]
results = await asyncio.gather(*tasks)
for res in results:
print(f"URL: {res['url']}\nTitle: {res['title']}\n")
if __name__ == "__main__":
asyncio.run(main())
五、注意事项
- 遵守robots.txt
使用aiohttp_robots包检查爬取权限 - 频率控制
添加随机延迟:await asyncio.sleep(random.uniform(0.5, 2.0)) # 随机延时 - 资源释放
显式关闭未完成的响应:if not response.closed: await response.release()
异步爬虫相较同步方案速度可提升 $n$ 倍($n$ 为并发数),但需注意:
- 目标服务器承受能力
- 避免触发反爬机制
- 分布式扩展时使用
Redis+Celery架构
更多推荐
所有评论(0)