Python 模塊 aiohttp



上次進行網站檢測的時候說到若是網站太多檢測太慢怎麼辦,這個問題解決方法有不少種,好比多線程、多進程、異步 IO,咱們首先看一下這三者的區別。python



概述 web


首先咱們看一下多進程、多線程、異步 IO,三者的區別。多進程顧名思義就是多個進程處理任務,多線程顧名思義就是多個線程處理任務,無論是多線程仍是多進程,設置多少個線程或者進程是一個大難題!多了,系統資源消耗太高;少了,併發性就不夠了。那麼,有沒有什麼辦法能夠減小大量進程或者線程的建立產生的大量內存佔用?實際上是有的,就是利用所謂的線程池或者進程池;既然減小了建立和銷燬對象產生的開銷,那麼進程或者線程切換的開銷有沒有辦法減小呢?實際上是有的,咱們直接使用異步 IO 就能夠了,異步 IO 其實是異步非阻塞 IO,就是讓保證一個線程或者進程在當前的 IO 請求還未完成的時候去執行其餘任務,既不須要申請大量的系統資源,也不會產生阻塞,所以異步 IO 成了加快檢測速度的首選。
redis

僅僅知道這些停留在理論還不夠,咱們還須要知道 Python 的異步 IO 相關模塊,這樣的模塊很是多,好比 aiohttp、gevent……由於我這裏是爲了加速網站請求,要求一個單位時間內請求大量的網站,因此在這裏我選擇 aiohttp 這個模塊。算法


同步耗時 微信


咱們先來測試一下不使用異步 IO 處理上次講網站檢測的那些網站檢測完成須要多久時間,仍是上次的代碼,我在這裏只給出須要修改的代碼,首先從 time 模塊導入一個名叫 time 的函數(即 from time import time),而後直接在 if __name__ == '__main__' 裏面改爲以下所示就好了:session

 if __name__ == '__main__':
     start = time()
     website_detection = WebsiteDetection()
     website_detection.filter()
     website_detection.detect()
     website_detection.save()
     print(time()-start)
 

運行結果如圖所示。
多線程


異步耗時 併發


在講解異步耗時以前,咱們首先須要把代碼中的 detect 方法改爲異步,這太簡單了,直接給出修改後的完整代碼。app

 from asyncio import get_event_loop
 from time import time
 from aiohttp import ClientSession
 from redis.client import Redis
 
 
 class WebsiteDetection:
     def __init__(self):
         self.websites = open('websites.txt').readlines()
         self.status_code_score = {'5': 0, '4': 1, '3': 2, '2': 3}
         self.website_score = {}
 
     async def detect(self):
         async with ClientSession(headers={
             'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239'
                           '.132 Safari/537.36 QIHU 360SE'})as session:
             for website in self.websites:
                 print(website)
                 async with session.get(website)as response:
                     self.website_score[website] = self.status_code_score[str(response.status)[0]]
 
     def filter(self):
         self.websites = {'/'.join(website.strip('\n').split('/', maxsplit=3)[:-1])+'/'for website in self.websites}
 
     def save(self):
         redis = Redis()
         for website, score in self.website_score.items():
             redis.zadd('websites', website, score)
         redis.connection_pool.disconnect()
 
 
 if __name__ == '__main__':
     start = time()
     website_detection = WebsiteDetection()
     website_detection.filter()
     get_event_loop().run_until_complete(website_detection.detect())
     website_detection.save()
     print(time()-start)
 

運行結果如圖所示。
機器學習

和同步相比差了沒多少,可是確實能夠發現異步的效率要比同步高,爲何這裏差了沒多少主要是由於網站數量太少了,異步和同步並沒什麼太大的區別,若是有幾千個甚至幾萬個網站可能差距就出來了。

今天的文章有不懂的能夠後臺回覆「加羣」,備註:小陳學Python,不備註但是會被拒絕的哦~!









本文分享自微信公衆號 - Python機器學習算法說書人(Python-ML-Algorithm)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索