python aiohttp异步实现HTTP请求

  

在python的HTTP库中,有requests、aiohttp和httpx。

requests只能发送同步请求,aiohttp只能发送异步请求,httpx既能发送同步请求,也能发送异步请求。

aiohttp在异步请求上效率最快,我们来一起学习下:

介绍

  aiohttp核心是异步并发,基于asyncio/await,可实现单线程并发IO操作。

安装

   pip install aiohttp

使用

  客户端使用

复制代码
import aiohttp,asyncio
async def my_request():
    async with aiohttp.ClientSession() as session:
       # verify_ssl = False # 防止ssl报错
        async with session.get('http://www.csdn.net/',verify_ssl=False) as response:
            print('status:',response.status)
            print('content-type',response.headers['content-type'])
            html=await response.text()
            print(f'body:{html[:15]}')
# 创建事件循环
loop=asyncio.get_event_loop()
tasks=[my_request(),]
loop.run_until_complete(asyncio.wait(tasks))
复制代码

运行结果:

 

 *python3.7以上版本运行使用asyncio.run(my_request())

 

  服务端使用

复制代码
import aiohttp,asyncio
async def hello(request):
    name=request.match_info.get('name','jack')
    text='hello '+name
    return web.Response(text=text)
app=web.Application()
app.add_routes([
    web.get('/',hello),
    web.get('/{name}',hello)
])
web.run_app(app,host='127.0.0.1')
复制代码

 

  aiohttp客户端的简单应用

复制代码
async def get_html(session,url):
#发送一个get请求信息
async with session.get(url,verify_ssl=False) as response:
print('status:',response.status)
return await response.text()
async def main():
#建立客户端会话
async with aiohttp.ClientSession() as session:
html1=await get_html(session,'http://www.csdn.net/')
html2=await get_html(session,'http://python.org')
print(html1)
print(html2)

loop= asyncio.get_event_loop()
tasks=[main(),]
loop.run_until_complete(asyncio.wait(tasks))
复制代码

以上例子也可以发送POST、DELETE、PUT方法,请求参数还有headers,params,data等。

  aio 异步爬虫

复制代码
复制代码
import aiohttp,asyncio
import time
async def get_html(session,url):
    print('发送请求:',url)
    async with session.get(url,verify_ssl=False)as response:
        content=await response.content.read()
        print('得到结果',url,len(content))
        filename=url.rsplit('/')[-1]
        print('正在下载',filename)
        with open(filename,'wb') as file_object:
            file_object.write(content)
            print(filename,'下载成功')
async def main():
    async with aiohttp.ClientSession() as session:
        start_time=time.time()
        url_list=[
            'https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093544wallpaper1.jpg',
            'https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093557wallpaper2.jpg',
            'https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093613wallpaper3.jpg',
        ]

        tasks=[loop.create_task(get_html(session,url))for url in url_list]
        await asyncio.wait(tasks)
        end_time=time.time()
        print('is cost',round(end_time-start_time),'s')

loop=asyncio.get_event_loop()
loop.run_until_complete(main())
复制代码

 

复制代码

 

 ClientSession部分重要参数:

  1.TCPConnector 用于常规TCP套接字(同时支持HTTP和HTTPS方案)(绝大部分使用)。

  2.UnixConnector 用于通过UNIX套接字进行连接(主要用于测试)。

所有的连接器都应继承自BaseConnector。

#创建一个TCPConnector

conn=aiohttp.TCPConnector(verify_ssl=False)

#作为参数传入ClientSession

async with aiohppt.ClientSession(connector=conn) as session:

 

TCPConnector比较重要的参数有:

  verify_ssl(bool):布尔值,对HTTPS请求执行SSL证书验证(默认情况下启动),当要跳过具有无效证书的站点的验证时可设置为False.

  limit(int):整型,同时连接的总数。如果limit为None,则connector没有限制。(默认值:100)。

  limit_per_host(int):限制同时连接到同一个端点的总数。如果(host,port,is_ssl)三者相同,则端点相同。如果linit=0,则没有限制。

限制并发量的另一个做法(使用Semaphore)

使用Semaphore直接限制发送请求。

复制代码
import backoff as backoff
import requests,time,logging,aiohttp,asyncio
from requests.adapters import HTTPAdapter

# logging.basicConfig(level=logging.DEBUG)

my_logger=logging.getLogger(__name__)
my_handler=logging.FileHandler('log.txt')
my_handler.setLevel(logging.DEBUG)
formatter=logging.Formatter("%(asctime)s %(levelname)s %(pathname)s %(filename)s %(funcName)s %(lineno)s"
                            " -%(message)s","%Y-%m-%d %H:%M:%S")
my_handler.setFormatter(formatter)
my_logger.addHandler(my_handler)
my_logger.setLevel(logging.DEBUG)


now = lambda: time.time()
@backoff.on_exception(backoff.expo,aiohttp.ClientError,max_tries=3,logger=my_logger)
async def get_html(session,i,url):
    start=now()
    async with session.get(url,verify_ssl=False) as response:
        # return await response.text()
        r=await response.read()
        end_time=now()
        cost=end_time-start
        msg='第{}个请求,开始时间:{},花费时间:{},返回信息:{}\n'.format(i,start,cost,r.decode('utf-8'))
        print('running %d'% i,now(),msg)

# 使用semaphore 限制最大并发数
async def bound_register(sem,session,i,url):
    async with sem:
        await get_html(session,i,url)

async def run(num,url):
    tasks=[]
    sem=asyncio.Semaphore(100)
    connector=aiohttp.TCPConnector(limit=0,verify_ssl=False)
    async with aiohttp.ClientSession(connector=connector) as session:
        for i in range(num):
            task=asyncio.ensure_future(
                bound_register(sem=sem,session=session,i=i,url=url)
            )
            tasks.append(task)
        responses=asyncio.gather(*tasks)
        await  responses
start=now()
number=200
# url2='http://www.baidu.com'
url='http://127.0.0.1:8000/rest/href/single_href/?title=6'
loop=asyncio.get_event_loop()
future=asyncio.ensure_future(run(number,url))
loop.run_until_complete(future)
print('总耗时: %0.3f' % (now() - start))
复制代码

 

 

 

 

 

参考文章:https://www.cnblogs.com/blueberry-mint/p/13937205.html

 

posted @   瘦阿瘦  阅读(1868)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示