aiohttp 高并发web服务_Python 全栈:教你搭建基于 aiohttp 的高并发爬虫

本文介绍了如何使用aiohttp构建异步爬虫,对比了requests、requests+线程池与aiohttp的性能,展示aiohttp在高并发场景下的优势。通过实例,展示了aiohttp在访问2000次本地服务时所需时间最短。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

今天这篇属于 asyncio 的应用篇,asyncio 的应用包括 web 服务端、爬虫应用、数据库连接库、分布式任务队列等领域。这里我们重点讲的是爬虫领域,使用的模块是 aiohttp。同样的和前面的教程一样,这里我们使用的 Python 版本同样为 3.8。

关于 aiohttp

Python 标准库的 asyncio 模块,内部实现了对 TCP、UDP、SSL 协议的异步操作方式,但是没有直接提供 HTTP 的异步操作方式。所以如果需要使用 HTTP 协议,我们就需要用到一个第三方的模块 aiohttp。

aiohttp 是一个基于 asyncio 的异步 http 网络模块分为了客户端和服务端,同时支持 websocket 的使用。在写爬虫时提供异步网络请求,而我们常用到的 requests 库是同步库,它会阻塞住 asyncio 所以不能在异步的环境中直接使用(这里不是说不能用,而是不能像写同步代码一样用它。我们需要用 run_in_executor 来运行,因为这属于使用额外线程的操作,开销上也是不小,所以不推荐大家使用)。

aiohttp 分为服务端和客户端,因为我们主要写爬虫程序所以我们重点说的是客户端的开发。

requests 和 requests+线程池以及使用 aiohttp 对比

首先,我们看一下使用 requests 进行循环访问、requests+线程池 、以及使用 aiohttp 这三种方式访问网址 2000 次返回最终结果的所用时间。 首先我们我通过 aiohttp 创建了一个本地的服务,地址为 127.0.0.1:5000。 先不要关注代码细节 代码如下:

from aiohttp import web

async def home(request: web.Request) -> web.Response:

return web.Response(text="Hi")

async def init_app() -> web.Application:

app = web.Application()

app.add_routes([web.get("/", home)])

return app

web.run_app(init_app(), port=5000)

之后打开我们的爬虫端分别测试上面三种结果的访问 2000 次的时间 测试代码如下

import requests

import timeit

from concurrent.futures import ThreadPoolExecutor

import aiohttp

import asyncio

session = requests.session()

url = "http://127.0.0.1:5000"

Count = 2000

def req(url: str):

req = requests.get(url)

req.status_code

def requests_test():

"""

第一组:循环的方式

:return:

"""

for i in range(Count):

req(url)

def pool_requests_test():

"""

第二组:线程池的方式

:return:

"""

url_list = [url for _ in range(Count)]

with ThreadPoolExecutor(max_workers=20) as pool:

pool.map(req, url_list)

async def fetch(url: str):

async with aiohttp.TCPConnector(ssl=False) as tc:

async with aiohttp.ClientSession(connector=tc) as session:

async with session.get(url) as req:

req.status

async def start():

tasks = [asyncio.create_task(fetch(url)) for _ in range(Count)]

await asyncio.wait(tasks)

def aiohttp_test():

"""

第三组:aiohttp 的方式

:param url:

:return:

"""

asyncio.run(start())

if __name__ == '__main__':

# 循环的

print(timeit.timeit(stmt=requests_test, number=1))

# 使用线程池的

print(timeit.timeit(stmt=pool_requests_test, number=1))

# 使用 aiohttp 的

# print(timeit.timeit(stmt=aiohttp_test, number=1))

测试了一共三次得到的结果如下: 第一次

3.08348508

2.1871939129999998

1.154268153

第二次

3.0424138099999998

2.395021737

1.315619199

第三次

2.953041779

2.242499116

1.14594682

很明显使用 aiohttp 的程序访问 2000 次时用时最短的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值