直接用 aiohttp.clientsession() 会报 runtimeerror: there is no current event loop in thread,因其必须运行在 asyncio 事件循环中,需用 asyncio.run() 包裹主函数启动,不可在普通函数或无循环环境中直接调用。

为什么直接用 aiohttp.ClientSession() 会出错?
新手常卡在第一步:新建 session 就报 RuntimeError: There is no current event loop in thread。这不是代码写错了,而是没启动 asyncio 环境。aiohttp 必须运行在事件循环里,不能像 requests 那样直接调用。
- 必须用
asyncio.run()包裹主函数,这是最简启动方式 - 别在普通函数里调
await,所有异步操作得在async def函数内 - 如果嵌入 Flask/Django,要用
asyncio.create_task()或显式获取当前 loop,不能硬套asyncio.run()
aiohttp.get() 和 session.get() 哪个该用?
永远用 session.get(),别碰裸的 aiohttp.get()。前者复用 TCP 连接、自动管理 cookie、支持连接池;后者每次新建连接,性能暴跌且容易被封。
-
ClientSession应该整个爬取过程只创建一次,不是每个请求都 new 一个 - 加
timeout=aiohttp.ClientTimeout(total=10)参数,避免单个请求卡死拖垮全部任务 - 务必设
headers,尤其User-Agent,否则很多网站直接返回 403
并发数设多少才不被封又不拖慢?
不是越多越好。实测起点小说网在并发 15~25 时稳定,超 30 就开始 429 或连接重置;而 httpbin 这类测试站能扛住 100+。关键看目标站反爬强度和你本地带宽。
- 用
asyncio.Semaphore(20)控制最大并发,比裸gather安全得多 - 别依赖
sleep限速——它只是让协程空转,不释放连接,反而加重服务端压力 - 真实延迟要靠
await asyncio.sleep(0.1)+ 请求间随机抖动(比如random.uniform(0.05, 0.2))
解析 HTML 时 BeautifulSoup 会阻塞吗?
会。BS4 的 BeautifulSoup(html, 'lxml') 是同步 CPU 密集操作,放在 await 链里会拖慢整个事件循环。这不是 aiohttp 的问题,是解析库本身没异步接口。
- 把解析逻辑放到
loop.run_in_executor()里,交给线程池执行 - 或者换
parsel库,它的Selector(text=html)构造快,CSS/XPath 提取也轻量,基本不卡 event loop - 千万别在
for tag in soup.find_all(...)里再发异步请求——嵌套 await 容易失控,先攒 URL 列表再统一调度
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











