aiohttp簡介與簡單使用
簡介
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()掛起任務(非同步執行)並獲取最終結果。