当前位置:首页>python>Python爬虫零基础实战⑧:aiohttp异步高性能爬虫,百倍提速并发请求,彻底解决requests串行爬取慢、效率低难题

Python爬虫零基础实战⑧:aiohttp异步高性能爬虫,百倍提速并发请求,彻底解决requests串行爬取慢、效率低难题

  • 2026-10-11 06:14:13
Python爬虫零基础实战⑧:aiohttp异步高性能爬虫,百倍提速并发请求,彻底解决requests串行爬取慢、效率低难题

标签:#Python爬虫 #aiohttp异步爬虫 #并发请求 #高性能爬虫 #爬虫提速优化

前言

截止上一篇,我们掌握了全套常规爬虫技能:静态解析、动态渲染、批量分页、数据存储、反爬突破、完整项目实战。

但所有基于 requests 的爬虫,都有一个致命短板:同步串行执行。

简单说就是:一次只能请求一个页面,必须等上一个请求结束、响应返回,才能执行下一次请求。

如果需要爬取几十、上百条数据,串行爬取耗时会成倍叠加,速度极慢、效率极低,完全无法满足批量采集需求。

想要突破爬虫速度瓶颈,必须解锁异步并发爬虫!

本篇详解爬虫高性能核心组合:asyncio + aiohttp,利用IO多路复用,在网络等待间隙并发发起多个请求,爬虫速度直接提升数十倍甚至上百倍,零基础也能轻松拿捏工业级高性能爬虫!


一、同步VS异步爬虫:零基础通俗对比

1、同步爬虫(requests)

执行逻辑:排队执行,串行等待

请求1 → 等待响应 → 请求2 → 等待响应 → 请求3...

缺点:大量时间浪费在「网络等待」,CPU全程闲置,资源浪费、速度极慢

2、异步爬虫(aiohttp)

执行逻辑:异步挂起,并发执行

同时发起多个请求,等待某一个请求响应时,程序自动去执行其他任务,不阻塞、不排队

优势:榨干网络与CPU性能,海量链接批量爬取,效率碾压同步爬虫


二、环境一键安装

aiohttp是Python专用异步网络请求库,需手动安装,终端执行豆瓣源加速安装命令:

pip install aiohttp -i https://pypi.douban.com/simple/

配套依赖说明

✅ asyncio:Python内置异步事件循环库,无需安装,负责管理异步任务

✅ aiohttp:异步网络请求核心库,替代同步requests

✅ aiohttp.ClientSession:异步会话对象,等同于requests.Session,全局复用更稳定


三、异步核心关键字(零基础必懂)

看懂这4个关键字,彻底入门异步编程,告别看不懂代码的困境:

1. async:修饰普通函数,将其变为异步函数,可被异步调用、可挂起等待

2. await:等待IO任务执行完成(网络请求、文件读取),等待期间不阻塞程序

3. create_task:创建异步任务,加入事件循环,实现并发执行

4. gather:批量收集所有异步任务结果,统一返回数据


四、最简入门:单次异步GET请求(可直接运行)

复刻requests基础请求,用aiohttp实现异步请求,适配浏览器伪装、超时容错,新手入门首选。

import aiohttpimport asyncio# 全局请求头伪装防爬HEADERS = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}# 异步请求函数async def fetch_single_url(session, url):    try:        # 异步发起GET请求,设置10秒超时        async with session.get(url, headers=HEADERS, timeout=aiohttp.ClientTimeout(total=10)) as resp:            html = await resp.text()            print(f"✅ 请求成功 状态码:{resp.status}")            return html    except Exception as e:        print(f"❌ 请求失败:{str(e)}")        return None# 异步主函数async def main():    # 全局创建异步会话,全程复用(核心!不要重复创建)    async with aiohttp.ClientSession() as session:        result = await fetch_single_url(session, "https://www.baidu.com")        print("页面源码长度:", len(result))# 启动异步程序入口if __name__ == "__main__":    asyncio.run(main())

新手核心禁忌:异步IO操作(text/json/read)必须加await,否则无法获取数据、代码直接报错!


五、核心实战:无限制批量并发请求

基于异步任务队列,一次性并发请求多个链接,对比同步爬虫,速度提升数十倍。适合少量链接快速测试。

import aiohttpimport asyncioHEADERS = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}async def fetch_url(session, url):    try:        async with session.get(url, headers=HEADERS, timeout=aiohttp.ClientTimeout(total=10)) as resp:            html = await resp.text()            print(f"✅ 成功爬取:{url} 状态码:{resp.status}")            return {"url": url, "html": html, "status": resp.status}    except Exception as e:        print(f"❌ 爬取失败 {url}:{str(e)}")        return {"url": url, "html": None, "status": 0}async def main():    # 批量请求链接列表    url_list = [        "https://www.baidu.com",        "https://www.qq.com",        "https://www.sogou.com",        "https://www.taobao.com"    ]    async with aiohttp.ClientSession() as session:        # 批量创建异步任务        task_list = [asyncio.create_task(fetch_url(session, url)) for url in url_list]        # 等待所有任务执行完成,收集结果        all_result = await asyncio.gather(*task_list)        # 遍历打印结果        for res in all_result:            print(f"链接:{res['url']} 源码长度:{len(res['html']) if res['html'] else0}")if __name__ == "__main__":    asyncio.run(main())

⚠️ 重要提醒:该方式无并发限制,少量链接可用,大批量爬取禁止使用!瞬间爆发大量请求,极易触发网站反爬、IP封禁。


六、生产级核心:信号量限制并发(必掌握)

真实项目中,必须限制最大并发数,模拟人工平稳访问,规避限流封禁,这是异步爬虫稳定运行的核心!

通过 asyncio.Semaphore 信号量,控制同时运行的请求数量,兼顾速度与稳定性。

import aiohttpimport asyncio# 核心配置:限制最大并发数(根据网站反爬强度调整,一般5-10最佳)MAX_CONCURRENT = 5HEADERS = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}async def safe_fetch(session, sem, url):    # 限制并发:同一时间最多执行MAX_CONCURRENT个任务    async with sem:        try:            async with session.get(url, headers=HEADERS, timeout=aiohttp.ClientTimeout(total=15)) as resp:                html = await resp.text()                print(f"✅ 爬取完成:{url}")                return url, html        except Exception as e:            print(f"❌ 爬取异常 {url}:{e}")            return url, Noneasync def main():    # 在main内部创建信号量(正确写法,绑定当前事件循环)    sem = asyncio.Semaphore(MAX_CONCURRENT)    # 批量生成15条测试链接    url_list = [f"https://www.baidu.com?page={i}" for i in range(1, 16)]    async with aiohttp.ClientSession() as session:        tasks = [asyncio.create_task(safe_fetch(session, sem, url)) for url in url_list]        results = await asyncio.gather(*tasks)    print("\n🎉 全部任务执行完成!")    # 遍历结果示例    # for url, html in results:    #     if html:    #         print(f"{url} 页面长度:{len(html)}")if __name__ == "__main__":    asyncio.run(main())

参数调试技巧

✅ 普通资讯网站:并发5-10

✅ 风控严格网站:并发2-3,降低请求频率

✅ 测试环境:可适当调高,生产环境保守配置


七、异步POST请求实战(表单/JSON参数)

适配登录接口、数据提交、参数请求场景,覆盖异步爬虫全场景需求。

import aiohttpimport asyncioasync def async_post():    url = "https://httpbin.org/post"    headers = {        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",        "Content-Type": "application/json"    }    # 提交JSON参数    post_data = {        "username": "spider_test",        "type": "async_crawl"    }    async with aiohttp.ClientSession() as session:        async with session.post(url, headers=headers, json=post_data) as resp:            # 异步解析JSON数据            res_data = await resp.json()            print("响应数据:", res_data)if __name__ == "__main__":    asyncio.run(async_post())

八、异步+数据解析完整实战(可直接项目复用)

整合异步并发请求 + BeautifulSoup数据解析 + 并发限制 + 异常容错,完整复刻工业级爬虫流程。

import aiohttpimport asynciofrom bs4 import BeautifulSoup# 并发限制配置MAX_CONCURRENT = 5HEADERS = {    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}# 异步请求+数据解析async def crawl_and_parse(session, sem, url):    async with sem:        try:            async with session.get(url, headers=HEADERS, timeout=aiohttp.ClientTimeout(total=10)) as resp:                html = await resp.text()                # 同步解析页面                soup = BeautifulSoup(html, "lxml")                title = soup.title.get_text().strip() if soup.title else "无标题"                print(f"✅ 解析成功:{url} | 标题:{title}")                return {"url": url, "title": title}        except Exception as e:            print(f"❌ 解析失败 {url}:{e}")            return Noneasync def main():    # 信号量必须在main内创建,绑定当前事件循环    sem = asyncio.Semaphore(MAX_CONCURRENT)    url_list = [        "https://www.baidu.com",        "https://www.qq.com",        "https://www.sogou.com"    ]    async with aiohttp.ClientSession() as session:        tasks = [asyncio.create_task(crawl_and_parse(session, sem, url)) for url in url_list]        result_list = await asyncio.gather(*tasks)        # 过滤空数据        valid_data = [res for res in result_list if res]        print(f"\n🎉 批量爬取完成,有效数据{len(valid_data)}条")if __name__ == "__main__":    asyncio.run(main())

九、新手高频踩坑汇总(避坑必看)

1、IO操作忘记加await

resp.text()、resp.json() 等网络IO操作,必须加await,否则返回协程对象,无法获取数据。

2、不限制并发数量

大批量爬取无信号量限制,瞬间并发爆炸,直接IP封禁,生产环境绝对禁止!

3、重复创建ClientSession

Session全局创建、全程复用,频繁新建会话会造成资源泄漏、请求不稳定。

4、异步用time.sleep延时

time.sleep()是同步阻塞方法,会卡死整个异步事件循环,异步延时必须用 await asyncio.sleep()。

5、不设置超时时间

部分网页请求卡死无响应,不设置超时会导致整个爬虫任务停滞、卡死。



文末结语

至此,你已经掌握爬虫两大核心体系:同步精准爬取 + 异步高速并发爬取。

requests适合小体量精准采集,aiohttp适合大体量批量高速采集,二者互补,适配所有爬虫场景。

异步爬虫是爬虫进阶的分水岭,也是项目实战、批量采集、数据落地的必备技能,吃透本篇,你的爬虫效率直接进阶工业级!

本篇所有模板代码可直接复制复用,建议收藏,后续所有批量爬虫项目均可直接套用!

最新文章

随机文章