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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于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保姆级教程