python異步協(xié)程(aiohttp,asyncio)

python異步協(xié)程

環(huán)境:python3.7.0

協(xié)程

協(xié)程避诽,英文叫做 Coroutine稚矿,又稱微線程砸狞,纖程闷堡,協(xié)程是一種用戶態(tài)的輕量級線程。

協(xié)程本質(zhì)上是個單進(jìn)程铐伴,協(xié)程相對于多進(jìn)程來說撮奏,無需線程上下文切換的開銷,無需原子操作鎖定及同步的開銷当宴,編程模型也非常簡單畜吊。

使用協(xié)程來實現(xiàn)異步操作,發(fā)出一個請求之后户矢,需要等待一定的時間才能得到響應(yīng)玲献,這個等待過程中,程序可以干許多其他的事情,等到響應(yīng)得到之后才切換回來繼續(xù)處理捌年,這樣可以充分利用 CPU 和其他資源瓢娜,這就是異步協(xié)程的優(yōu)勢。

通過異步協(xié)程可以加快爬蟲爬取文件的速度
其中用到aiohttp庫

sudo pip3 install aiohttp
Name: aiohttp
Version: 3.4.1
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: Nikolay Kim
Author-email: fafhrd91@gmail.com
License: Apache 2
Location: /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages
Requires: yarl, attrs, multidict, chardet, async-timeout
Required-by: 

以下分別是用異步與不用異步爬取unsplash首頁圖片的對比

unsplash.py
import requests
import os
import re
from time import time

class Spider(object):

    def __init__(self,n=10):
        self.headers={
            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
        }
        path='./download/unsplash'
        if not os.path.exists(path):
            os.mkdir(path)
            self.path=path
        else:
            self.path=path
        self.n=n
        self.num=1

    def getImagesLinks(self,page:int):
        url='https://unsplash.com/napi/photos'
        params={
            'page': page,
            'per_page': '12',
            'order_by': 'latest'
        }
        links=[]
        try:
            r=requests.get(url=url,params=params,timeout=60)
            r.raise_for_status()
            r.encoding=r.apparent_encoding
            for data in r.json():
                links.append(data['urls']['full'])
        except Exception as e:
            print(e.args)
        finally:
            return links

    def save_img(self,url):
        text=""
        try:
            r=requests.get(url,headers=self.headers,timeout=60)
            r.raise_for_status()
            text=r.content
        except Exception as e:
            print(e.args)
        finally:
            return text

    def download_img(self,url:str):
        url_split=re.split(r'\/|\?',url)
        try:
            filename=url_split[3]+'.jpg'
            if os.path.exists(self.path+'/'+filename):
                print('下載失敗礼预,文件已存在')
            else:
                with open(self.path+'/'+filename,'wb') as f:
                    f.write(self.save_img(url))
                    f.close()
                print('成功下載第%d張圖片'%(self.num))
                self.num+=1
        except Exception as e:
            print(e.args)
        finally:
            pass

    def run(self):
        try:
            for i in range(1,self.n+1):
                urls=self.getImagesLinks(i)
                for url in urls:
                    self.download_img(url)
        except Exception as e:
            print(e.args)
        finally:
            pass



def main():
    start=time()
    spider=Spider(n=1)
    spider.run()
    end=time()
    print(end-start,'s')

if __name__ == '__main__':
    main()
2.png

unsplash.py爬取里unsplash首頁的12張圖片,共耗時62.375s

async_unsplash.py
import requests
import re
import os
import asyncio
import aiohttp
from time import time



class Spider(object):

    def __init__(self,n=10):
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
        }
        path = './download/async_unsplash'
        if not os.path.exists(path):
            os.mkdir(path)
            self.path = path
        else:
            self.path = path
        self.n = n
        self.num=1

    def getImagesLinks(self,page:int):
        url='https://unsplash.com/napi/photos'
        params={
            'page': page,
            'per_page': '12',
            'order_by': 'latest'
        }
        links=[]
        try:
            r=requests.get(url=url,params=params,timeout=60)
            r.raise_for_status()
            r.encoding=r.apparent_encoding
            for data in r.json():
                links.append(data['urls']['full'])
        except Exception as e:
            print(e.args)
        finally:
            return links

    async def save_img(self,url):
        content=""
        try:
            async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
                response=await session.get(url,headers=self.headers,timeout=60)
                content=await response.read()
                await session.close()
        except Exception as e:
            print(e.args)
        finally:
            return content

    async def download_img(self,url:str):
        url_split = re.split(r'\/|\?', url)
        try:
            filename = url_split[3] + '.jpg'
            if os.path.exists(self.path + '/' + filename):
                print('下載失敗眠砾,文件已存在')
            else:
                content=await self.save_img(url)
                with open(self.path + '/' + filename, 'wb') as f:
                    f.write(content)
                    f.close()
                print('成功下載第%d張圖片' % (self.num))
                self.num+=1
        except Exception as e:
            print(e.args)
        finally:
            pass

    def run(self):
        try:
            for i in range(1, self.n + 1):
                urls = self.getImagesLinks(i)
                tasks=[asyncio.ensure_future(self.download_img(url)) for url in urls]
                loop=asyncio.get_event_loop()
                loop.run_until_complete(asyncio.wait(tasks))
        except Exception as e:
            print(e.args)
        finally:
            pass


def main():
    start=time()
    spider=Spider(n=1)
    spider.run()
    end=time()
    print(end-start,'s')

if __name__ == '__main__':
    main()

1.png

async_unsplash.py爬取里unsplash首頁的12張圖片,共耗時16.740s

通過上述兩個事例,可以很明顯看出異步協(xié)程對爬蟲爬取文件速度的提升,對別的程序運行也有同樣的作用

運行異步協(xié)程程序的時候,內(nèi)存的占有比不用時大

GitHub地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末托酸,一起剝皮案震驚了整個濱河市褒颈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌获高,老刑警劉巖哈肖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異念秧,居然都是意外死亡淤井,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門摊趾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來币狠,“玉大人,你說我怎么就攤上這事砾层′雒啵” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵肛炮,是天一觀的道長止吐。 經(jīng)常有香客問我,道長侨糟,這世上最難降的妖魔是什么碍扔? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮秕重,結(jié)果婚禮上不同,老公的妹妹穿的比我還像新娘。我一直安慰自己溶耘,他們只是感情好二拐,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凳兵,像睡著了一般百新。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庐扫,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天吟孙,我揣著相機(jī)與錄音澜倦,去河邊找鬼聚蝶。 笑死杰妓,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碘勉。 我是一名探鬼主播巷挥,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼验靡!你這毒婦竟也來了倍宾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤胜嗓,失蹤者是張志新(化名)和其女友劉穎高职,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辞州,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡怔锌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了变过。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片埃元。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖媚狰,靈堂內(nèi)的尸體忽然破棺而出岛杀,到底是詐尸還是另有隱情,我是刑警寧澤崭孤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布类嗤,位于F島的核電站,受9級特大地震影響辨宠,放射性物質(zhì)發(fā)生泄漏遗锣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一彭羹、第九天 我趴在偏房一處隱蔽的房頂上張望黄伊。 院中可真熱鬧,春花似錦派殷、人聲如沸还最。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拓轻。三九已至,卻和暖如春经伙,著一層夾襖步出監(jiān)牢的瞬間扶叉,已是汗流浹背勿锅。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留枣氧,地道東北人溢十。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像达吞,于是被迫代替她去往敵國和親张弛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 很多朋友對異步編程都處于“聽說很強大”的認(rèn)知狀態(tài)酪劫。鮮有在生產(chǎn)項目中使用它吞鸭。而使用它的同學(xué),則大多數(shù)都停留在知...
    星星在線閱讀 2,858評論 2 39
  • 轉(zhuǎn)一篇駒神的關(guān)于異步編程和Asyncio的文章覆糟。這是上篇刻剥,共三篇。原文地址:http://aju.space/20...
    SeanCheney閱讀 9,797評論 2 99
  • 1 什么是異步編程 通過學(xué)習(xí)相關(guān)概念滩字,我們逐步解釋異步編程是什么造虏。 1.1 阻塞 程序未得到所需計算資源時被掛起的...
    hugoren閱讀 2,656評論 2 10
  • 1. 前言 在執(zhí)行一些 IO 密集型任務(wù)的時候酗电,程序常常會因為等待 IO 而阻塞。比如在網(wǎng)絡(luò)爬蟲中内列,如果我們使用 ...
    NewForMe閱讀 405評論 0 1
  • 出來混话瞧,遲早是要還的嫩与。這江湖鐵律當(dāng)然也適用于綠茵場。 但誰先還交排,什么時候還划滋,這是個問題。主要看門柱和門將的心情埃篓。 ...
    諸葛不亮008閱讀 170評論 0 0