簡介
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()掛起任務(異步執行)並獲取最終結果。