Python基础入门 Day119 异步 I/O 实战:使用 aiohttp 进行高并发网络请求

92次阅读
没有评论

共计 2359 个字符,预计需要花费 6 分钟才能阅读完成。

在上一节我们学习了协程的基本概念以及 async/await 的使用方式。本篇我们将进一步深入异步编程的实战部分,重点讲解如何利用 aiohttp 来实现高并发网络请求,这在爬虫、API 调用、分布式任务中极其重要。


一、为什么使用 aiohttp?

Python 标准库的 asyncio 并不能直接发送 HTTP 请求,而 aiohttp 正是为异步网络 I/O 而生的库。

相比传统同步方式(如 requests):

  • 同步:一次只能等待一个请求返回
  • 异步:同时发起多个请求,用事件循环调度等待

这使得 aiohttp 在高并发访问场景下性能优势极大。


二、安装 aiohttp

如果你尚未安装,请使用:

pip install aiohttp

三、使用 aiohttp 发送异步请求

下面是最基本的 GET 请求示例:

import aiohttp
import asyncio

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.text()

async def main():
    url = "https://www.python.org/"
    content = await fetch(url)
    print(content[:200])

asyncio.run(main())

要点解析:

  • ClientSession:用于管理连接池,提高性能
  • await resp.text():异步读取内容
  • async with:确保连接自动关闭,避免资源泄露

四、并发请求:批量抓取多个网页

高并发的精髓在于 asyncio.gather

import aiohttp
import asyncio

async def fetch(url, session):
    async with session.get(url) as resp:
        text = await resp.text()
        print(f"{url} 获取成功 ")
        return text

async def main():
    urls = [
        "https://www.python.org/",
        "https://www.github.com/",
        "https://www.wikipedia.org/",
        "https://www.qq.com/",
        "https://www.bing.com/"
    ]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch(url, session) for url in urls]
        results = await asyncio.gather(*tasks)

asyncio.run(main())

优点:

  • 所有请求并发执行
  • 性能远超同步代码
  • 对 I/O 密集任务效率提升显著

五、限制并发数量(避免压力过大)

过高的并发可能压垮网站或自己的网络,需要设置 Semaphore:

import aiohttp
import asyncio

sem = asyncio.Semaphore(5)  # 最多 5 个并发

async def fetch(url, session):
    async with sem:
        async with session.get(url) as resp:
            print(f" 抓取:{url}")
            return await resp.text()

async def main():
    urls = [... 同上...]

    async with aiohttp.ClientSession() as session:
        tasks = [fetch(url, session) for url in urls]
        await asyncio.gather(*tasks)

asyncio.run(main())

这样可以有效控制请求数量,避免触发网站的反爬机制。


六、异常处理:防止程序中断

加入 try/except 捕获异常并继续执行:

async def fetch(url, session):
    try:
        async with session.get(url, timeout=5) as resp:
            return await resp.text()
    except Exception as e:
        print(f" 请求失败:{url},原因:{e}")
        return None

七、实战案例:批量爬取网页标题

示例解析网页标题 <title>

import aiohttp
import asyncio
import re

async def fetch_title(url, session):
    try:
        async with session.get(url) as resp:
            text = await resp.text()
            title = re.search(r"<title>(.*?)</title>", text, re.S)
            print(f"{url} 标题:{title.group(1) if title else ' 未找到 '}")
    except:
        print(f"{url} 获取失败 ")

async def main():
    urls = [
        "https://www.python.org/",
        "https://www.github.com/",
        "https://www.bilibili.com/"
    ]
    async with aiohttp.ClientSession() as session:
        await asyncio.gather(*(fetch_title(url, session) for url in urls))

asyncio.run(main())

八、小结

在本篇中你学习了:

  • aiohttp 的基本使用方式
  • 如何进行异步并发请求
  • 如何限制并发数量
  • 如何处理异常
  • 如何编写实战爬虫应用

异步 I/O 是 Python 现代工程中非常重要的一环,掌握 aiohttp 能显著提升你的程序性能。

如果你需要继续下一篇(Day120),告诉我即可。

正文完
 0
评论(没有评论)