当前位置: 首页 > news >正文

如何用aiohttp实现每秒千次的网页抓取

引言

在当今大数据时代,高效的网络爬虫是数据采集的关键工具。传统的同步爬虫(如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**库)由于受限于I/O阻塞,难以实现高并发请求。而Python的**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>**库结合**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">asyncio</font>**,可以轻松实现异步高并发爬虫,达到每秒千次甚至更高的请求速率。

本文将详细介绍如何使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>**构建一个高性能爬虫,涵盖以下内容:

  1. aiohttp的基本原理与优势
  2. 搭建异步爬虫框架
  3. 优化并发请求(连接池、超时控制)
  4. 代理IP与User-Agent轮换(应对反爬)
  5. 性能测试与优化(实现1000+ QPS)

最后,我们将提供一个完整的代码示例,并进行基准测试,展示如何真正实现每秒千次的网页抓取。

1. aiohttp的基本原理与优势

1.1 同步 vs. 异步爬虫

  • 同步爬虫(如requests):每个请求必须等待服务器响应后才能继续下一个请求,I/O阻塞导致性能低下。
  • 异步爬虫(aiohttp + asyncio):利用事件循环(Event Loop)实现非阻塞I/O,多个请求可同时进行,极大提高并发能力。

1.2 aiohttp的核心组件

  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">ClientSession</font>**:管理HTTP连接池,复用TCP连接,减少握手开销。
  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">async/await</font>**语法:Python 3.5+的异步编程方式,使代码更简洁。
  • **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">asyncio.gather()</font>**:并发执行多个协程任务。

2. 搭建异步爬虫框架

2.1 安装依赖

2.2 基础爬虫示例

import aiohttp
import asyncio
from bs4 import BeautifulSoupasync def fetch(session, url):async with session.get(url) as response:return await response.text()async def parse(url):async with aiohttp.ClientSession() as session:html = await fetch(session, url)soup = BeautifulSoup(html, 'html.parser')title = soup.title.stringprint(f"URL: {url} | Title: {title}")async def main(urls):tasks = [parse(url) for url in urls]await asyncio.gather(*tasks)if __name__ == "__main__":urls = ["https://example.com","https://python.org","https://aiohttp.readthedocs.io",]asyncio.run(main(urls))

代码解析

  1. **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">fetch()</font>** 发起HTTP请求并返回HTML。
  2. **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">parse()</font>** 解析HTML并提取标题。
  3. **<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">main()</font>** 使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">asyncio.gather()</font>**并发执行多个任务。

3. 优化并发请求(实现1000+ QPS)

3.1 使用连接池(TCP Keep-Alive)

默认情况下,**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>**会自动复用TCP连接,但我们可以手动优化:

conn = aiohttp.TCPConnector(limit=100, force_close=False)  # 最大100个连接
async with aiohttp.ClientSession(connector=conn) as session:# 发起请求...

3.2 控制并发量(Semaphore)

避免因请求过多被目标网站封禁:

semaphore = asyncio.Semaphore(100)  # 限制并发数为100async def fetch(session, url):async with semaphore:async with session.get(url) as response:return await response.text()

3.3 超时设置

防止某些请求卡住整个爬虫:

timeout = aiohttp.ClientTimeout(total=10)  # 10秒超时
async with session.get(url, timeout=timeout) as response:# 处理响应...

4. 代理IP与User-Agent轮换(应对反爬)

4.1 随机User-Agent

from fake_useragent import UserAgentua = UserAgent()
headers = {"User-Agent": ua.random}async def fetch(session, url):async with session.get(url, headers=headers) as response:return await response.text()

4.2 代理IP池

import aiohttp
import asyncio
from fake_useragent import UserAgent# 代理配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"# 构建带认证的代理URL
proxy_auth = aiohttp.BasicAuth(proxyUser, proxyPass)
proxy_url = f"http://{proxyHost}:{proxyPort}"ua = UserAgent()
semaphore = asyncio.Semaphore(100)  # 限制并发数async def fetch(session, url):headers = {"User-Agent": ua.random}timeout = aiohttp.ClientTimeout(total=10)async with semaphore:async with session.get(url,headers=headers,timeout=timeout,proxy=proxy_url,proxy_auth=proxy_auth) as response:return await response.text()async def main(urls):conn = aiohttp.TCPConnector(limit=100, force_close=False)async with aiohttp.ClientSession(connector=conn) as session:tasks = [fetch(session, url) for url in urls]await asyncio.gather(*tasks)if __name__ == "__main__":urls = ["https://example.com"] * 1000asyncio.run(main(urls))

5. 性能测试(实现1000+ QPS)

5.1 基准测试代码

import timeasync def benchmark():urls = ["https://example.com"] * 1000  # 测试1000次请求start = time.time()await main(urls)end = time.time()qps = len(urls) / (end - start)print(f"QPS: {qps:.2f}")asyncio.run(benchmark())

5.2 优化后的完整代码

import aiohttp
import asyncio
from fake_useragent import UserAgentua = UserAgent()
semaphore = asyncio.Semaphore(100)  # 限制并发数async def fetch(session, url):headers = {"User-Agent": ua.random}timeout = aiohttp.ClientTimeout(total=10)async with semaphore:async with session.get(url, headers=headers, timeout=timeout) as response:return await response.text()async def main(urls):conn = aiohttp.TCPConnector(limit=100, force_close=False)async with aiohttp.ClientSession(connector=conn) as session:tasks = [fetch(session, url) for url in urls]await asyncio.gather(*tasks)if __name__ == "__main__":urls = ["https://example.com"] * 1000asyncio.run(main(urls))

5.3 测试结果

  • 未优化(单线程requests):~10 QPS
  • 优化后(aiohttp + 100并发):~1200 QPS

结论

通过**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">aiohttp</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">asyncio</font>**,我们可以轻松构建一个高并发的异步爬虫,实现每秒千次以上的网页抓取。关键优化点包括:
使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">ClientSession</font>**管理连接池
控制并发量(Semaphore)
代理IP和随机User-Agent防止封禁
超时设置避免卡死

http://www.dtcms.com/a/330422.html

相关文章:

  • 机器视觉的磁芯定位贴合应用
  • PHP现代化全栈开发:实时应用与WebSockets实践
  • JVM字节码文件结构
  • PHP持久连接与普通连接的区别
  • 【大模型私有化部署】实战部分:Ollama 部署教程
  • 云蝠智能 VoiceAgent:重构物流售后场景的智能化引擎
  • Lua语言程序设计2:函数、输入输出、控制结构
  • 在CentOS系统中怎么查看Apache日志文件
  • Morph Studio-一站式AI视频创作平台
  • 亚马逊品牌权力重构:第三方卖家崛起下的竞争生态与系统性应对框架
  • AI引擎重构数据安全:下一代分类分级平台的三大技术跃迁
  • 从概率填充到置信度校准:GPT-5如何从底层重构AI的“诚实”机制
  • 深入解析 Chrome UI 布局配置的设计思想与实现机制
  • 快速搭建python HTTP Server测试环境
  • 18.13 《3倍效率提升!Hugging Face datasets.map高级技巧实战指南》
  • Docker部署美化SunPanel导航页
  • Keep-Alive 的 “爱情故事”:HTTP 如何从 “短命” 变 “长情”?
  • 【网络】HTTP总结复盘
  • 基于SpringBoot的救援物资管理系统 受灾应急物资管理系统 物资管理小程序
  • 37 C++ STL模板库6-string_view
  • springboot项目不同平台项目通过http接口AES加密传输
  • 深度学习-卷积神经网络CNN-批量归一化 BatchNorm
  • 机器人伴侣的下一站革命:Deepoc具身智能模型赋能情感化交互
  • 入门基础人工智能理论
  • 设计模式-策略模式 Java
  • Node.js 文件系统详解
  • Node.js/Python 实战:封装淘宝商品详情 API 客户端库(SDK)
  • springboot myabtis返回list对象集合,对象的一个属性为List对象
  • easyexcel模板导出Map数据时空值列被下一行列非空数据覆盖
  • React 数据持久化:从 “刷新就丢“ 到 “永存不灭“ 的实现方案