一、简介
aiohttp 是一个基于异步的 Python HTTP 客户端/服务器框架,它允许你编写高性能的异步网络应用程序。它建立在 Python 的协程和异步 I/O 模型上,并利用了 Python 3.5+ 中引入的 asyncio 库。官网:https://docs.aiohttp.org
- 异步支持:aiohttp 基于 asyncio 库,充分利用了 Python 的协程和异步 I/O 模型,可以处理大量并发请求而不阻塞其他任务。这使得它非常适合编写高性能的网络应用程序。
客户端功能:aiohttp 提供了一个强大的异步 HTTP 客户端,可以发送各种类型的 HTTP 请求(GET、POST、PUT、DELETE 等)。它支持自定义请求头、查询参数、请求体,并可以处理响应的文本、字节、JSON 等格式。 - 服务器功能:aiohttp 还提供了一个异步 HTTP 服务器框架,可以用于构建高性能的 Web 应用程序。你可以定义路由、处理请求和响应、处理表单数据、设置静态文件等。
- WebSocket 支持:aiohttp 提供了对 WebSocket 协议的支持,可以轻松地建立双向通信的实时应用程序。
中间件支持:aiohttp 具有中间件机制,你可以编写自定义中间件来处理请求和响应,例如身份验证、日志记录、错误处理等。 - Cookie 和会话管理:aiohttp 提供了对 Cookie 的支持,可以方便地设置和处理 Cookie。此外,它还支持会话管理,可以跟踪用户的会话状态。
- SSL/TLS 支持:aiohttp 支持使用 SSL/TLS 加密进行安全的 HTTPS 通信。
- 扩展性:aiohttp 具有模块化的设计,允许你使用插件和扩展来增加功能,例如模板引擎、数据库集成等
二、安装
pip install aiohttp
三、ClientSession 类的方法和属性
- aiohttp.ClientSession():异步 HTTP 客户端会话,用于管理与服务器的连接池,返回ClientSession对象
- connector:连接器对象,用于管理连接池和处理底层的网络连接。
- loop:事件循环对象。
- cookies:CookieJar 对象,用于管理会话的 Cookie。
- headers:默认的请求头部信息,可以是字典。
- skip_auto_headers:不自动添加的默认头部信息,可以是列表。
- auth:默认的身份验证信息,可以是 aiohttp.BasicAuth对象。
- json_serialize:JSON 序列化函数,默认为 json.dumps。
- version:HTTP 版本,默认为 aiohttp.HttpVersion11。
- cookie_jar:CookieJar 对象,用于管理会话的 Cookie。
- read_timeout:读取超时时间(秒)。
- conn_timeout:连接超时时间(秒)。
- raise_for_status:是否在收到非 2xx 响应时引发异常。
- trust_env:是否信任环境变量中的代理设置。
- ws_response_class:WebSocket 响应类,默认为 aiohttp.ClientResponse。
- ClientSession.request(method, url, **kwargs):发送自定义的 HTTP 请求,并返回一个 ClientResponse 对象。
- method:请求的方法,如 ‘GET’、‘POST’ 等。
- url:请求的 URL。
- params:URL 查询参数,可以是字典。
- data:请求的数据,可以是字符串或字节。
- json:JSON 数据,会自动设置请求的 ‘Content-Type’ 为 ‘application/json’。
- headers:请求的头部信息,可以是字典。
- skip_auto_headers:不自动添加的头部信息,可以是列表
- cookies:请求的 Cookie,可以是字典或 http.cookies.SimpleCookie 对象。
- auth:身份验证信息,可以是 aiohttp.BasicAuth对象。
- allow_redirects:是否允许重定向。
- max_redirects:最大重定向次数。
- encoding:请求的编码方式。
- compress:是否启用压缩。
- chunked:是否启用分块传输编码。
- expect100:是否启用 “Expect: 100-continue”。
- read_until_eof:是否读取直到响应结束。
- proxy:代理 URL。
- proxy_auth:代理身份验证信息,可以是 aiohttp.BasicAuth 对象。
- timeout:请求超时时间(秒)。
- ssl:SSL/TLS 配置。
- proxy_headers:代理请求的头部信息,可以是字典。
- trace_request_ctx:请求上下文。
- ClientSession.get(url, **kwargs):发送 GET 请求,参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.post(url, **kwargs):发送 POST 请求,参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.options(url, **kwargs):发送 OPTIONS 请求。参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.head(url, **kwargs、s):发送 HEAD 请求。参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.put(url, **kwargs):发送 PUT 请求。参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.patch(url, **kwargs):发送 PATCH 请求。参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.delete(url, **kwargs):发送 DELETE 请求。参数与 request() 方法相同,返回一个 ClientResponse 对象
- ClientSession.ws_connect(url, **kwargs):创建一个 WebSocket 连接。
- url:WebSocket 的 URL。
- protocols:协议列表。
- timeout:连接超时时间(秒)。
- max_msg_size:最大消息大小。
- autoclose:是否自动关闭连接。
- autoping:是否自动发送心跳。
- heartbeat:心跳间隔时间(秒)。
- headers:请求的头部信息,可以是字典。
- proxy:代理 URL。
- proxy_auth:代理身份验证信息,可以是 aiohttp.BasicAuth对象。
- ssl:SSL/TLS 配置。
- origin:请求的来源。
- compress:是否启用压缩。
- method:请求的方法,默认为 ‘GET’。
- auth:身份验证信息,可以是 aiohttp.BasicAuth对象。
- loop:事件循环对象
- ClientSession.close():关闭 ClientSession 对象,释放与服务器的连接。
- ClientSession.cookie_jar:一个 CookieJar 对象,用于管理 Cookie。
- ClientSession.headers:一个 CIMultiDictProxy 对象,表示请求的头部信息。
- ClientSession.cookies:默认的 Cookie。
- ClientSession.connector:一个 TCPConnector 对象,用于管理与服务器的连接。
- ClientSession.timeout:一个 Timeout 对象,用于设置请求的超时时间。
- ClientSession.get_connector(self):获取连接器对象。
- ClientSession.loop:事件循环对象。
- ClientSession.auth:默认的身份验证信息。
- ClientSession.raise_for_status:是否在收到非 2xx 响应时引发异常。
- ClientSession.trust_env:是否信任环境变量中的代理设置。
四、ClientResponse 类的方法和属性
- ClientResponse.status:响应的状态码。
- ClientResponse.reason:响应的原因短语。
- ClientResponse.headers:响应的头部信息,一个 CIMultiDictProxy 对象。
- ClientResponse.cookies:响应的 Cookie,一个 CookieJar 对象。
- ClientResponse.content:响应的内容,以字节形式返回
- content.read():读取响应内容的原始字节。await response.content.read()
- content.readany():读取响应内容的原始字节,返回一个 bytes 对象。await response.content.readany()
- content.readline():读取响应内容的原始字节,返回一个 bytes 对象。await response.content.readline()
- ClientResponse.read():读取响应的内容,以字节形式返回。
- ClientResponse.text():以文本形式返回响应的内容。
- ClientResponse.json():将响应的内容解析为 JSON 格式,并返回解析后的对象。
- ClientResponse.raise_for_status():如果响应的状态码表明请求失败(4xx 或 5xx),则引发一个异常。
- ClientResponse.raw_headers:响应的原始头部信息,以元组列表的形式返回。
- ClientResponse.url:响应的 URL。
- ClientResponse.release():释放响应对象的资源。
- ClientResponse.close():关闭响应对象。
- ClientResponse.get_encoding():获取响应的编码方式。
- ClientResponse.get_content_type():获取响应的内容类型。
- ClientResponse.get_links():获取响应中的链接信息。
- ClientResponse.get_history():获取重定向历史记录。
- ClientResponse.get_request_info():获取请求信息对象。
- ClientResponse.get_writer():获取写入器对象。
- ClientResponse.get_task():获取任务对象。
- ClientResponse.get_loop():获取事件循环对象。
- ClientResponse.get_traces():获取跟踪信息。
- ClientResponse.get_timer():获取计时器对象。
- ClientResponse.get_continue():检查是否收到 “100 Continue” 响应。
- ClientResponse.ok:布尔值,表示响应是否成功(状态码为 2xx)。
- ClientResponse.reason_phrase:响应的状态原因短语。
- ClientResponse.content_type:响应的内容类型。
- ClientResponse.content_length:响应的内容长度。
- ClientResponse.charset:响应的字符编码。
- ClientResponse.history:重定向历史记录。
- ClientResponse.request_info:请求信息对象。
- ClientResponse.writer:写入器对象。
- ClientResponse.task:任务对象。
- ClientResponse.loop:事件循环对象。
- ClientResponse.traces:跟踪信息。
- ClientResponse.timer:计时器对象。
- ClientResponse.continue100:是否收到 “100 Continue” 响应。
- ClientResponse.connection:响应的连接对象。
- ClientResponse.is_eof():检查响应是否已经结束。
五、ClientRequest 类的方法和属性
- aiohttp.ClientRequest():异步 HTTP 客户端的请求对象,用于构建和发送 HTTP 请求,返回ClientRequest对象
- method:请求的方法,如 ‘GET’、‘POST’ 等。
- url:请求的 URL。
- params:URL 查询参数,可以是字典。
- headers:请求的头部信息,可以是字典。
- skip_auto_headers:不自动添加的头部信息,可以是列表。
- data:请求的数据,可以是字符串或字节。
- json:JSON 数据,会自动设置请求的 ‘Content-Type’ 为 ‘application/json’。
- cookies:请求的 Cookie,可以是字典或 http.cookies.SimpleCookie 对象。
- auth:身份验证信息,可以是 aiohttp.BasicAuth对象。
- allow_redirects:是否允许重定向。
- max_redirects:最大重定向次数。
- encoding:请求的编码方式。
- compress:是否启用压缩。
- chunked:是否启用分块传输编码。
- expect100:是否启用 “Expect: 100-continue”。
- read_until_eof:是否读取直到响应结束。
- proxy:代理 URL。
- proxy_auth:代理身份验证信息,可以是 aiohttp.BasicAuth对象。
- timeout:请求超时时间(秒)。
- ssl:SSL/TLS 配置。
- proxy_headers:代理请求的头部信息,可以是字典。
- trace_request_ctx:请求上下文。
六、web之aiohttp.web.Application()
- aiohttp.web.Application(**kwargs) 创建 Web 应用程序,app = aiohttp.web.Application()
- router:指定应用程序的路由表对象。默认为 None,表示将创建一个新的路由表对象。
- middlewares:指定应用程序的中间件列表。中间件是在请求处理过程中执行的额外操作,例如身份验证、日志记录等。默认为一个空列表。
- default_host:指定应用程序的默认主机名。默认为 None,表示没有默认主机。
- default_port:指定应用程序的默认端口号。默认为 None,表示没有默认端口。
- client_max_size:指定应用程序接受的请求体的最大大小(以字节为单位)。默认为 1024^2(1MB)。
- loop:指定应用程序使用的事件循环。默认为 None,表示使用 * asyncio.get_event_loop() 获取默认事件循环。
- handler_args:指定传递给请求处理函数的额外参数。默认为一个空字典。
- debug:指定是否启用调试模式。调试模式下,应用程序会提供更详细的错误信息。默认为 False
- app.router:获取应用程序的路由表对象,用于定义和管理应用程序的路由。
- app.add_routes(routes):向应用程序添加一组路由。routes 参数可以是 aiohttp.web.RouteTableDef 对象或包含路由的可迭代对象。
- app.on_startup(callback, *args, **kwargs):注册应用程序启动时要调用的回调函数。callback 是要注册的回调函数,*args 和 **kwargs 是传递给回调函数的额外参数。
- app.on_shutdown(callback, *args, **kwargs):注册应用程序关闭时要调用的回调函数。callback 是要注册的回调函数,args 和 **kwargs 是传递给回调函数的额外参数。
- app.cleanup():清理应用程序的资源。这将依次调用已注册的关闭回调函数。
- app.make_handler(,access_log_class=AccessLogger, access_log_format=DEFAULT_ACCESS_LOG_FORMAT, access_log=DEFAULT_ACCESS_LOG_FORMAT, **kwargs):创建一个 aiohttp.web.RequestHandler 对象,用于处理 HTTP 请求。
- access_log_class:指定访问日志的记录器类。默认为 AccessLogger,用于记录请求的访问日志。
- access_log_format:指定访问日志的格式。默认为 DEFAULT_ACCESS_LOG_FORMAT,包含常见的访问日志字段。
- access_log:指定访问日志的格式。默认为 DEFAULT_ACCESS_LOG_FORMAT,与 access_log_format 参数相同。
- app.middlewares:应用程序的中间件列表。中间件可以在请求处理过程中执行额外的操作,例如身份验证、日志记录等。
- app.middlewares.append(middleware_handler):添加中间件
- app.middlewares.remove(middleware_handler):移除中间件
- app.middlewares.clear():清空中间件列表
- app.on_startup:应用程序启动时要调用的回调函数列表。
- app.on_shutdown:应用程序关闭时要调用的回调函数列表。
- app.route:获取应用程序的路由器对象
- app.route.add_route(method, path, handler, *, name=None):添加一个路由
- method:HTTP 方法,指定该路由匹配的请求方法。可以是字符串或字符串列表。
- path:URL 路径模式,指定该路由匹配的 URL 路径。
- handler:处理该路由的处理程序。可以是一个函数、一个类的方法,或者是一个 web.View 的子类。
- name:可选,路由的名称,用于在应用程序中引用该路由。
- app.route.add_get(path, handler, *, name=None):添加一个 GET 请求方法的路由。
- app.route.add_post(path, handler, *, name=None):添加一个 POST 请求方法的路由。
- app.route.add_put(path, handler, *, name=None):添加一个 PUT 请求方法的路由。
- app.route.add_delete(path, handler, *, name=None):添加一个 DELETE 请求方法的路由。
- app.route.add_static(prefix, path, *, name=None):添加一个静态文件路由
- prefix:URL 前缀,用于匹配静态文件请求的 URL。
- path:静态文件目录的路径。
- name:可选,路由的名称,用于在应用程序中引用该路由
- app.route.add_view(path, handler, *, name=None):添加一个基于类的视图路由。
- path:URL 路径模式,指定该路由匹配的 URL 路径。
- handler:处理该路由的视图类。
- name:可选,路由的名称,用于在应用程序中引用该路由。
七、web之 web.RouteTableDef()路由表
- web.RouteTableDef() 创建路由表,routes = web.RouteTableDef()
- @routes.route(method,path, **kwargs)
- routes.get(path, **kwargs)
- @routes.post(path, **kwargs)
- @routes.put(path, **kwargs)
- @routes.patch(path, **kwargs)
- @routes.delete(path, **kwargs)
- @routes.options(path, **kwargs)
- @routes.head(path, **kwargs)
- @routes.trace(path, **kwargs)
- routes.static() 装饰器添加静态文件路由
八、web之 web.Response 创建并返回给客户端的 HTTP 响应对象
- web.Response() 创建并返回给客户端的 HTTP 响应对象,reponse = web.Response()
- body:响应体的内容。可以是字符串、字节串或文件对象。默认为 None。
- status:响应的状态码。默认为 200。
- reason:响应状态码的原因短语。默认为 None,将根据状态码自动确定原因短语。
- text:响应体的内容,以字符串形式。与 body 参数互斥,只能选择其中一个。
- content_type:响应的内容类型。默认为 None,表示不指定内容类型。
- charset:响应的字符集。默认为 None。
- headers:响应的自定义头部。可以是一个字典或 aiohttp 的 CIMultiDict 对象。
- content_encoding:响应体的内容编码。默认为 None。
- zlib_executor_size:指定用于压缩响应体的线程池的大小。它是一个整数值,表示线程池中的线程数量。默认为 None,表示不使用线程池压缩响应体。
- zlib_executor:指定用于压缩响应体的线程池。它是一个 * concurrent.futures.Executor 对象,用于执行压缩操作。默认为 None。
- body:响应体的内容。可以是字符串、字节串或文件对象。
- status:响应的状态码。
- reason:响应状态码的原因短语。
- text:响应体的内容,以字符串形式。
- content_type:响应的内容类型。
- charset:响应的字符集。
- headers:响应的头部,一个 aiohttp 的 CIMultiDict 对象。
- content_encoding:响应体的内容编码。
- cookies:响应的 cookie,一个 aiohttp 的 CIMultiDict 对象。
- chunked:表示响应是否使用分块传输编码。
九、web之 web.Request 获取请求相关的信息和属性,路由中参数都会有一个request
- request.method:请求的 HTTP 方法,如 GET、POST 等。
- request.path:请求的路径部分。
- request.query_string:请求的查询字符串部分。
- request.headers:请求的头部,一个 aiohttp 的 CIMultiDict 对象。
- request.cookies:请求的 cookie,一个 aiohttp 的 CIMultiDict 对象。
- request.content_type:请求的内容类型。
- request.charset:请求的字符集。
- request.query:解析后的查询参数,一个 MultiDictProxy 对象。
- request.match_info:URL 匹配的信息,一个 MatchInfo 对象。
- request.version:HTTP 版本。
- request.host:请求的主机名。
- request.scheme:请求的协议方案,如 “http” 或 “https”。
- request.remote:请求的远程地址信息。
- request.app:请求所属的 Application 对象。
十、web之 web.WebSocketResponse,处理 WebSocket 连接,提供了与客户端进行双向通信的接口
- web.WebSocketResponse() 创建socket对象,ws = web.WebSocketResponse()
- ws.prepare(request): 准备 WebSocket 连接。在处理 WebSocket 连接之前,需要先调用这个方法进行准备。
- ws.send_str(data): 发送文本消息给客户端。
- ws.send_bytes(data): 发送二进制消息给客户端。
- ws.receive(): 接收客户端发送的消息。返回一个 WSMessage 对象,其中包含消息的类型和数据。
- ws.close(): 关闭 WebSocket 连接。
- ws.closed: WebSocket 连接是否已关闭。
- ws.exception(): 如果 WebSocket 连接因异常而关闭,返回关闭时的异常对象。
十一、web之 aiohttp.CookieJar 管理 Cookie
- aiohttp.CookieJar(unsafe=True):创建cookiejar,cookie_jar = aiohttp.CookieJar(unsafe=True)
- cookie_jar.update_cookies(cookies, response_url=None):从字典或 http.cookies.SimpleCookie 对象中更新 Cookie。可以通过指定 response_url 参数来限制 Cookie 的作用域。
- cookie_jar.filter_cookies(url):根据给定的 URL 过滤并返回适用于该 URL 的 Cookie。返回一个 http.cookies.SimpleCookie 对象。
- cookie_jar.clear():清除所有的 Cookie。
- cookie_jar.load(filename):从文件中加载 Cookie。
- cookie_jar.save(filename):将 Cookie 保存到文件中。
十二、案例
- 爬取英雄联盟官方皮肤
'''网址:https://101.qq.com/#/hero'''import aiohttp import asyncio import json import os class LOL: request_url = { 'hero_info': 'https://game.gtimg.cn/images/lol/act/img/js/heroList/hero_list.js?ts=2822604', 'skin': 'https://game.gtimg.cn/images/lol/act/img/skin/big{}00{}.jpg' } headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36' } def __init__(self): pass async def get_hero(self): async with aiohttp.ClientSession() as request: response = await request.get(self.request_url['hero_info'],headers=self.headers) hero_json_str = await response.text() task_list = [] for item in json.loads(hero_json_str)['hero']: task = asyncio.create_task(self.get_skin(request,item)) task_list.append(task) await asyncio.wait(task_list) async def get_skin(self,request,hero_info): if not os.path.exists(hero_info["name"]): os.mkdir(hero_info["name"]) for nu in range(30): response = await request.get(self.request_url['skin'].format(hero_info['heroId'], nu)) if response.status == 200: skin_info = await response.read() with open(f'{hero_info["name"]}{os.sep}{nu}.jpg', 'wb') as file: file.write(skin_info) print('英雄皮肤已下载') else: breakif __name__ == '__main__': lol = LOL() asyncio.run(lol.get_hero())
- 创建web应用程序之web.RouteTableDef()
from aiohttp import web import os routes = web.RouteTableDef() @routes.get('/') #访问http://localhost:8009/ def index(request): response = web.Response(text="Hello, world!") return response @routes.route('GET','/test') #访问http://localhost:8009/test def test(request): response = web.Response(text="测试") return response routes.static('/skin',path=os.path.join(os.getcwd(),'img')) #访问http://localhost:8009/skin/万花通灵/0.jpg web.static('/skin',path=os.path.join(os.getcwd(),'img')) #访问http://localhost:8009/skin/万花通灵/0.jpg app = web.Application() app.add_routes(routes) web.run_app(app,host='localhost',port=8009)
- 创建web应用程序之app.router
from aiohttp import web import os def index(request): response = web.Response(text="Hello, world!") return response def test(request): response = web.Response(text="测试") return response app = web.Application() app.router.add_get('/',index)#访问http://localhost:8009/ app.router.add_route('GET','/test',test) #访问http://localhost:8009/test app.router.add_static('/skin',path=os.path.join(os.getcwd(),'img')) #访问http://localhost:8009/skin/万花通灵/0.jpg web.static('/skin',path=os.path.join(os.getcwd(),'img')) #访问http://localhost:8009/skin/万花通灵/0.jpg web.run_app(app,host='localhost',port=8009)
- 创建web应用程序之中间件
from aiohttp import web # 定义全局中间件函数 @web.middleware async def middleware_handler(request, handler): # 在请求处理之前执行的代码 print('全局请求处理之前执行的代码') # 调用下一个中间件或请求处理函数 response = await handler(request) # 在请求处理之后执行的代码 print('全局请求处理之后执行的代码') return response # 定义test路由中间件函数 @web.middleware async def test_handler(request, handler): # 在请求处理之前执行的代码 print('test路由在请求处理之前执行的代码') # 调用下一个中间件或请求处理函数 response = await handler(request) # 在请求处理之后执行的代码 print('test路由在请求处理之后执行的代码') return response # 创建应用程序 app = web.Application() routes = web.RouteTableDef() @routes.get('/') async def index(request): return web.Response(text='首页') # 定义处理函数 async def test_response(request): return web.Response(text='测试') @routes.get('/test') async def test(request): response = await test_handler(request,test_response) return response # 将中间件添加到应用程序 app.middlewares.append(middleware_handler) app.add_routes(routes) web.run_app(app,host='localhost',port=8009)
- websocket案例
from aiohttp import web # WebSocket 处理函数 async def websocket_handler(request): ws = web.WebSocketResponse() # 创建 WebSocketResponse 对象 await ws.prepare(request) # 准备 WebSocket 连接 async for msg in ws: # 处理 WebSocket 的消息 if msg.type == web.WSMsgType.TEXT: if msg.data == 'close': await ws.close() else: await ws.send_str('You said: ' + msg.data) elif msg.type == web.WSMsgType.ERROR: print('WebSocket connection closed with exception %s' % ws.exception()) return ws # 创建应用程序 app = web.Application() # 将 WebSocket 处理函数添加到路由中 app.router.add_get('/ws', websocket_handler) # 运行应用程序 web.run_app(app)