Python使用aiohttp实现每秒千次的网页抓取

 更新时间:2025年08月28日 10:43:56   作者:小白学大数据  
在当今大数据时代,高效的网络爬虫是数据采集的关键工具,传统的同步爬虫由于受限于I/O阻塞,难以实现高并发请求,而Python的aiohttp可以轻松实现异步高并发爬虫,达到每秒千次甚至更高的请求速率,所以本文介绍了Python如何使用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 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. **<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)  # 限制并发数为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

结论

通过**<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防止封禁
  • 超时设置避免卡死

以上就是Python使用aiohttp实现每秒千次的网页抓取的详细内容,更多关于Python aiohttp网页抓取的资料请关注脚本之家其它相关文章!

相关文章

  • Scrapy将数据保存到Excel和MySQL中的方法实现

    Scrapy将数据保存到Excel和MySQL中的方法实现

    本文主要介绍了Scrapy将数据保存到Excel和MySQL中的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • python机器学习理论与实战(二)决策树

    python机器学习理论与实战(二)决策树

    这篇文章主要介绍了python机器学习理论与实战第二篇,决策树的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Django csrf 验证问题的实现

    Django csrf 验证问题的实现

    csrf是通过伪装来自受信任用户的请求来利用受信任的网站。这篇文章主要介绍了Django csrf 验证问题的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • python使用rstrip函数删除字符串末位字符

    python使用rstrip函数删除字符串末位字符

    rstrip函数用于删除字符串末位指定字符,默认为空白符,这篇文章主要介绍了python使用rstrip函数删除字符串末位字符的方法,需要的朋友可以参考下
    2023-04-04
  • python添加不同目录下路径导致vscode无法识别这些路径的问题及操作步骤

    python添加不同目录下路径导致vscode无法识别这些路径的问题及操作步骤

    本文介绍了Python中动态添加路径导致VSCode扩展(如Pylance)无法识别的问题,提出通过配置python.analysis.extraPaths和启用executeinfiledir两种解决方案,确保路径正确且区分运行方式,以解决代码补全、文件读取等问题,感兴趣的朋友跟随小编一起看看吧
    2025-06-06
  • Python实现将json格式数据存储到Mysql数据库

    Python实现将json格式数据存储到Mysql数据库

    这篇文章主要为大家详细介绍了如何使用Python实现将json格式数据存储到Mysql数据库,文中的示例代码简洁易懂,有需要的小伙伴可以参考下
    2025-03-03
  • python远程连接服务器MySQL数据库

    python远程连接服务器MySQL数据库

    这篇文章主要为大家详细介绍了python远程连接服务器MySQL数据库,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Python 字符替换的四方法

    Python 字符替换的四方法

    本文主要介绍了Python 字符替换的四方法,主要包括replace、translate、maketrans 和正则这是四种方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Python提取Pdf文件内容的操作方法(表格、文本、图片)

    Python提取Pdf文件内容的操作方法(表格、文本、图片)

    本文主要介绍了Python提取PDF内容的方法(文本、图像、表格),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • Python实现的简单万年历例子分享

    Python实现的简单万年历例子分享

    这篇文章主要介绍了Python实现的简单万年历例子分享,需要的朋友可以参考下
    2014-04-04

最新评论