简介
aiohttp是一个为Python提供异步HTTP客户端/服务端编程,基于asyncio(Python用于支持异步编程的标准库)的异步库
核心功能
- 同时支持客户端使用和服务端使用
- 同时支持服务端WebSockets组件和客户端WebSockets组件
- web服务器具有中间件、信号组件和可插拨路由的功能
安装
安装命令如下(推荐使用python3.7或以上版本)
pip3 install aiohttp
如果你想把chardet、aiodns和brotlipy一同安装的话,可以使用以下命令安装
pip3 install aiohttp[speedups]
快速开始
客户端使用
简单发送一个http请求
import aiohttp
import asyncio
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('http://python.org') as response:
print('Status:', response.status)
print('Content-type:', response.headers['content-type'])
html = await response.text()
print(f'Body: {html[:15]}...')
if __name__ == '__main__':
asyncio.run(main())
结果如下
Status: 200
Content-type: text/html; charset=utf-8
Body: <!doctype html>...
服务端使用
简单搭建一个web服务
from aiohttp import web
# 视图函数
async def hello(request):
name = request.match_info.get('name', 'Python')
text = f'Hello, {name}'
return web.Response(text=text)
app = web.Application()
app.add_routes([
web.get('/', hello),
web.get('/{name}', hello)
]) # 添加路由
if __name__ == '__main__':
web.run_app(app, host='127.0.0.1')
一个简单的服务就成功搭建了,在浏览器*问http://127.0.0.1:8080或者http://127.0.0.1:8080/name(name为你输入的字符串)就可以看到对应的返回信息。
aiohttp客户端的简单应用
基本API的使用
aiohttp提供了一个简单发送HTTP请求的协程方法:aiohttp.request()
基本API对于不需要持久连接,cookies和复杂的连接附件(如SSL证书)的HTTP请求来说是比较好用的,它的用法和python网络请求requests包的用法差不多。
import aiohttp
import asyncio
async def get_html():
async with aiohttp.request('GET', 'http://python.org/') as resp:
print(resp.status)
print(await resp.text())
if __name__ == '__main__':
asyncio.run(get_html())
以上例子,aiohttp.request()中的第一个参数为method(HTTP方法),第二个参数为url(请求链接),其他比较重要的关键字参数还有headers(请求头信息)、cookies(请求时携带的cookies)、params(原url组合的参数)、data(请求体的参数)等。
客户端会话
客户端会话(Client Session)是比较推荐使用的发起HTTP请求的接口。
会话(Session)封装有一个连接池(连接池实例),默认支持持久连接。除非需要连接非常多不同的服务器,否则还是建议你在应用程序中只使用一个会话(Session),这样有利于连接池。
import aiohttp
import asyncio
async def get_html(session, url):
# 发送一个GET请求获取页面信息
async with session.get(url) as resp:
print(f'--- current url is {url} ---')
print('Status:', resp.status)
return await resp.text()
async def main():
# 建立一个客户端会话
async with aiohttp.ClientSession() as session:
html1 = await get_html(session, 'http://python.org')
html2 = await get_html(session, 'https://baidu.com')
print(html1)
print(html2)
if __name__ == '__main__':
asyncio.run(main())
通过aiohttp.ClientSession()创建一个客户端会话session,session可以使用get和post等请求方法发送请求,相关参数也是类似requests包的传参。
aiohttp异步爬虫
我们来使用aiohttp实现一个简单的爬虫,爬取三张图片
import time
import aiohttp
import asyncio
async def get_html(session, url):
print('发送请求:', url)
async with session.get(url) as response:
content = await response.content.read()
print('得到结果', url, len(content))
filename = url.rsplit('/')[-1]
print(f'正在下载{filename}...')
with open(filename, 'wb') as file_object:
file_object.write(content)
print(f'{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 = [asyncio.create_task(get_html(session, url)) for url in url_list]
await asyncio.wait(tasks)
end_time = time.time()
print(f'it cost {round(end_time - start_time, 4)}s.')
if __name__ == '__main__':
asyncio.run(main())
执行结果如下
发送请求: 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
得到结果 https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093613wallpaper3.jpg 1215029
正在下载o_201106093613wallpaper3.jpg...
o_201106093613wallpaper3.jpg下载成功
得到结果 https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093544wallpaper1.jpg 1326652
正在下载o_201106093544wallpaper1.jpg...
o_201106093544wallpaper1.jpg下载成功
得到结果 https://images.cnblogs.com/cnblogs_com/blueberry-mint/1877253/o_201106093557wallpaper2.jpg 1867449
正在下载o_201106093557wallpaper2.jpg...
o_201106093557wallpaper2.jpg下载成功
it cost 0.1745s.
本例子中先创建一个客户端会话session,在session使用asyncio.create_task()创建3个协程任务,然后通过asyncio.wait()挂起任务(异步执行)并获取最终结果。