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

小白学大数据
• 阅读 0

引言 在当今大数据时代,高效的网络爬虫是数据采集的关键工具。传统的同步爬虫(如requests库)由于受限于I/O阻塞,难以实现高并发请求。而Python的aiohttp库结合asyncio,可以轻松实现异步高并发爬虫,达到每秒千次甚至更高的请求速率。 本文将详细介绍如何使用aiohttp构建一个高性能爬虫,涵盖以下内容:

  1. aiohttp的基本原理与优势
  2. 搭建异步爬虫框架
  3. 优化并发请求(连接池、超时控制)
  4. 代理IP与User-Agent轮换(应对反爬)
  5. 性能测试与优化(实现1000+ QPS) 最后,我们将提供一个完整的代码示例,并进行基准测试,展示如何真正实现每秒千次的网页抓取。
  6. aiohttp的基本原理与优势
  7. 1 同步 vs. 异步爬虫 ● 同步爬虫(如requests):每个请求必须等待服务器响应后才能继续下一个请求,I/O阻塞导致性能低下。 ● 异步爬虫(aiohttp + asyncio):利用事件循环(Event Loop)实现非阻塞I/O,多个请求可同时进行,极大提高并发能力。
  8. 2 aiohttp的核心组件 ● ClientSession:管理HTTP连接池,复用TCP连接,减少握手开销。 ● async/await语法:Python 3.5+的异步编程方式,使代码更简洁。 ● asyncio.gather():并发执行多个协程任务。
  9. 搭建异步爬虫框架
  10. 1 安装依赖
  11. 2 基础爬虫示例 import aiohttp import asyncio from bs4 import BeautifulSoup

async 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.string print(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. fetch() 发起HTTP请求并返回HTML。
  2. parse() 解析HTML并提取标题。
  3. main() 使用asyncio.gather()并发执行多个任务。
  4. 优化并发请求(实现1000+ QPS)
  5. 1 使用连接池(TCP Keep-Alive) 默认情况下,aiohttp会自动复用TCP连接,但我们可以手动优化: conn = aiohttp.TCPConnector(limit=100, force_close=False) # 最大100个连接 async with aiohttp.ClientSession(connector=conn) as session:

    发起请求...

  6. 2 控制并发量(Semaphore) 避免因请求过多被目标网站封禁: semaphore = asyncio.Semaphore(100) # 限制并发数为100

async 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 UserAgent

ua = 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"] * 1000 asyncio.run(main(urls)) 5. 性能测试(实现1000+ QPS) 5.1 基准测试代码 import time

async 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 UserAgent

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) 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"] * 1000 asyncio.run(main(urls)) 5.3 测试结果 ● 未优化(单线程requests):10 QPS ● 优化后(aiohttp + 100并发):1200 QPS 结论 通过aiohttp和asyncio,我们可以轻松构建一个高并发的异步爬虫,实现每秒千次以上的网页抓取。关键优化点包括: ✅ 使用ClientSession管理连接池 ✅ 控制并发量(Semaphore) ✅ 代理IP和随机User-Agent防止封禁

点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Irene181 Irene181
4年前
详解4种类型的爬虫技术
导读:网络爬虫是一种很好的自动采集数据的通用手段。本文将会对爬虫的类型进行介绍。作者:赵国生王健来源:大数据DT(ID:hzdashuju)聚焦网络爬虫是“面向特定主题需求”的一种爬虫程序,而通用网络爬虫则是捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分,主要目的是将互联网上的网页下载到本地,形成一个互联网内
Aimerl0 Aimerl0
4年前
Python网络爬虫与信息提取
title:Python网络爬虫与信息提取date:2020121001:00:23tags:Pythoncategories:学习笔记写在前面不知道写啥其实说实话TOC网络爬虫之规则安装requests库cmd命令行打开输入pip3installrequests,等待即可简单测试,爬一下bkjwpythonimportrequ
如何使用pholcus库进行多线程网页标题抓取以提高效率?
在当今信息爆炸的时代,数据抓取已成为获取信息的重要手段。Go语言因其高效的并发处理能力而成为编写爬虫的首选语言之一。pholcus库,作为一个强大的Go语言爬虫框架,提供了多线程抓取的能力,可以显著提高数据抓取的效率。本文将介绍如何使用pholcus库进行
智多星V+TNY264278 智多星V+TNY264278
12个月前
采集数据的时候,碰到反爬虫程序怎么办?
当碰到反爬虫程序时,可以尝试以下几种方法来应对:一、调整访问频率降低请求速度:大多数反爬虫机制是基于访问频率来判断是否为爬虫的。如果采集数据时请求发送得过于频繁,很容易被目标网站识别出来。例如,原本你每秒发送10个请求,现在将其降低到每秒12个请求,使其更
小白学大数据 小白学大数据
4个月前
Scrapy结合Selenium实现滚动翻页数据采集
引言在当今的互联网数据采集领域,许多网站采用动态加载技术(如AJAX、无限滚动)来优化用户体验。传统的基于Requests或Scrapy的爬虫难以直接获取动态渲染的数据,而Selenium可以模拟浏览器行为,实现滚动翻页和动态内容加载。本文将介绍如何结合S
小白学大数据 小白学大数据
4个月前
Python爬虫多次请求后被要求验证码的应对策略
在互联网数据采集领域,Python爬虫是一种强大的工具,能够帮助我们高效地获取网页数据。然而,在实际应用中,许多网站为了防止恶意爬取,会在检测到频繁请求时要求用户输入验证码。这无疑给爬虫的正常运行带来了挑战。本文将详细介绍Python爬虫在多次请求后被要求
小白学大数据 小白学大数据
1个月前
优化 Python 爬虫性能:异步爬取新浪财经大数据
一、同步爬虫的瓶颈传统的同步爬虫(如requestsBeautifulSoup)在请求网页时,必须等待服务器返回响应后才能继续下一个请求。这种阻塞式I/O操作在面对大量数据时存在以下问题:速度慢:每个请求必须串行执行,无法充分利用网络带宽。易被封禁:高频
使用asyncio库和多线程实现高并发的异步IO操作的爬虫
摘要:本文介绍了如何使用Python的asyncio库和多线程实现高并发的异步IO操作,以提升爬虫的效率和性能。通过使用asyncio的协程和事件循环,结合多线程,我们可以同时处理多个IO任务,并实现对腾讯新闻网站的高并发访问。正文:在网络爬虫中,IO操作
异步爬虫实战:实际应用asyncio和aiohttp库构建异步爬虫
在网络爬虫的开发中,异步爬虫已经成为一种非常流行的技术。它能够充分利用计算机的资源,提高爬虫效率,并且能够处理大量的运算请求。Python中的asyncio和aiohttp库提供了强大的异步爬虫支持,使得开发者能够轻松构建高效的异步爬虫。什么是异动爬虫?为
小白学大数据
小白学大数据
Lv1
男 · 亿牛云 · python技术
宁为代码类弯腰,不为bug点提交!
文章
115
粉丝
5
获赞
18