異步網絡模塊之aiohttp的使用(一)


異步網絡模塊之aiohttp的使用(一)

平時我們也許用的更多的是requests模塊,或者是requests_hml模塊,但是他們都屬於阻塞類型的不支持異步,速度很難提高,於是后來出現了異步的grequests,開始了異步網絡請求,速度得到了大大的提升,但是今天我們要說的另外的一個比較異步網絡請求模塊-aiohttp。

什么是aiohhtp?

要學習一個模塊,首先要知道這個模塊都能做什么,我們從官網上找到了關於aiohttp的解釋。

Asynchronous HTTP Client/Server for asyncio and Python.
Supports both Client and HTTP Server.
Supports both Server WebSockets and Client WebSockets out-of-the-box without the Callback Hell.
Web-server has Middlewares, Signals and pluggable routing.

大概意思是說aiohttp是一個異步http網絡模塊分為了客戶端和服務端,同時支持websocket的使用,另外不用擔心在使用過程中多次回調導致回調地獄情況出現。

如何安裝?

在linux直接pip安裝應該沒什么問題,一般都坑在windows系統上,我使用win10 64位系統直接安裝也是沒有出現什么問題,
官網上推薦的是先按照cchardet,這是一個關於網頁編碼的模塊直接運行下面命令即可

pip install cchardet

之后我們安裝

pip install aiohttp

后面的操作我們需要還要安裝一個協程模塊asyncio。

pip install asyncio

ok,沒什么問題安裝我們就到這里了。

如何使用

我們先看一段代碼,后面會對代碼作出解釋。

import asyncio #導入協程包
import aiohttp #導入aiohttp 
from lxml import html   #導入html解析模塊
headers={"User-Agent""Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"
}
async def getsource(url):
       conn=aiohttp.TCPConnector(verify_ssl=False)#防止ssl報錯
       async with aiohttp.ClientSession(connector=conn) as session: #創建session
             async with session.get(url,headers=headers,timeout=60as req: #獲得請求
                 if req.status==200#判斷請求碼
                    source=await req.text()#使用await關鍵字獲取返回結果
                    print(html.fromstring(source).xpath("//title/text()")[0]) #獲取網頁標題
                 else:
                     print("訪問失敗")
if __name__=="__main__":
         full_urllist= 
["https://www.baidu.com","https://www.cnblogs.com","https://www.jianshu.com"]
         event_loop = asyncio.get_event_loop() #創建事件循環
         tasks = [getsource(url) for url in full_urllist]
         results = event_loop.run_until_complete(asyncio.wait(tasks))#等待任務結束

-----------------------------------------運行結果---------------------------------------------


部分內容已經在上面的代碼中標注了,下面我們開始對上面的內容進行分析。

 

async/await

首先我們需要知道關鍵字async/await,在方法的面前加關鍵字async之后該方法就成了一個協程了,
一般await關鍵字使用的使用所在的方法必須帶有async,關於兩個關鍵字的演變,要從yield說起,
演變過程請參考http://python.jobbole.com/86069/,這里只要知道是協程意思就行了。
首先我定義了連接器並取消ssl安全驗證,我們使用verify_ssl使其等於False,默認是True的。

TCPConnector

因為有的網站請求的時候會驗證ssl證書,如果是自簽名的ssl證書會出錯。

conn=aiohttp.TCPConnector(verify_ssl=False)#防止ssl報錯

下面是關於TCPConnector的所有參數部分。

class aiohttp.TCPConnector(*, ssl=None, verify_ssl=True, fingerprint=None, use_dns_cache=True, ttl_dns_cache=10, family=0, ssl_context=None, local_addr=None, resolver=None, keepalive_timeout=sentinel, force_close=False, limit=100, limit_per_host=0, enable_cleanup_closed=False, loop=None)

limit

為了限制同時打開的連接數量,我們可以將限制參數傳遞給連接器:

conn = aiohttp.TCPConnector(limit=30)#同時最大進行連接的連接數為30,默認是100,limit=0的時候是無限制

limit_per_host:

conn = aiohttp.TCPConnector(limit_per_host=30)#默認是0

同一端點的最大連接數量。同一端點即(host, port, is_ssl)完全相同.

ClientSession

首先我們創建一個session對象,向下面這樣使用async聲明異步,同時with上下文關鍵字 省去了關閉連接的代碼,

async with aiohttp.ClientSession(connector=conn) as session: 

下面是ClientSession的所有參數,這里用的比較多的是connector,headers,cookies其他的參數大家可以去自己探索一下。

class aiohttp.ClientSession(*, connector=None, loop=None, cookies=None, headers=None, skip_auto_headers=None, auth=None, json_serialize=json.dumps, version=aiohttp.HttpVersion11, cookie_jar=None, read_timeout=None, conn_timeout=None, timeout=sentinel, raise_for_status=False, connector_owner=True, auto_decompress=True, proxies=None

session.get

上面我們創建了session對象,然后我們就要進行請求具體的網站了。

async with session.get(url,headers=headers,timeout=60as req: #獲得請求

這一步我們像使用requests那樣傳入headers參數並指定最大超時為60s。

ClientResponse

然后我們判斷請求是否情況,之后我們使用await req.text()獲取了網頁的源碼,注意這里必須使用await關鍵字來獲取協程的結果。然后我們使用了lxml模塊獲取這三個網頁的title標題。

到目前為止我們只是定義了一個協程,並沒有真正的運行它接下來我們看看main方法是做什么的。

         full_urllist= 
["https://www.baidu.com","https://www.cnblogs.com","https://www.jianshu.com"]
         event_loop = asyncio.get_event_loop() #創建時間循環
         tasks = [getsource(url) for url in full_urllist]
         results = event_loop.run_until_complete(asyncio.wait(tasks))#等待任務結束

首先我定義了一個列表含有三個目標url,當前你可以定義更多。
asyncio.get_event_loop方法可以創建一個事件循環,然后使用run_until_complete將協程注冊到事件循環,並啟動事件循環。
協程對象不能直接運行,在注冊事件循環的時候,其實是run_until_complete方法將協程包裝成為了一個任務(task)對象。所謂task對象是Future類的子類。保存了協程運行后的狀態,用於未來獲取協程的結果。

asyncio.ensure_future(coroutine) 和 loop.create_task(coroutine)都可以創建一個task,run_until_complete的參數是一個futrue對象。當傳入一個協程,其內部會自動封裝成task,task是Future的子類。isinstance(task, asyncio.Future)將會輸出True。

簡單的我們就了解到這吧,如果有什么不懂的地方請留言大家一起討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM