黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

python爬蟲第11關(guān) 協(xié)程

系統(tǒng) 1897 0

協(xié)程是什么

我們已經(jīng)做過不少爬蟲項目,不過我們爬取的數(shù)據(jù)都不算太大,如果我們想要爬取的是成千上萬條的數(shù)據(jù),那么就會遇到一個問題:因為程序是一行一行依次執(zhí)行的緣故,要等待很久,我們才能拿到想要的數(shù)據(jù)。

既然一個爬蟲爬取大量數(shù)據(jù)要爬很久,那我們能不能讓多個爬蟲一起爬取?

這樣無疑能提高爬取的效率,就像一個人干不完的活兒,組個團隊一起干,活一下被干完了。

這是一個很好的思路——讓多個爬蟲幫我們干活。但具體怎么用Python實現(xiàn)這事呢?

我們可以先別急著想怎么實現(xiàn)這件事,后面我會跟你說。

現(xiàn)在,你先跟我想象一個情景:
python爬蟲第11關(guān) 協(xié)程_第1張圖片
相信你肯定會這么做:把三部電影都點擊下載??茨囊徊肯认螺d好了,就先看哪一部,讓還沒有下載完的電影持續(xù)保持下載狀態(tài)。

如果用計算機里的概念來解釋這件事的話:在一個任務(wù)未完成時,就可以執(zhí)行其他多個任務(wù),彼此不受影響(在看第一部下載好的電影時,其他電影繼續(xù)保持下載狀態(tài),彼此之間不受影響),叫異步。

有異步的概念,那應(yīng)該也有同步的概念吧?是的,同步就是一個任務(wù)結(jié)束才能啟動下一個(類比你看完一部電影,才能去看下一部電影)。
顯然,異步執(zhí)行任務(wù)會比同步更加節(jié)省時間,因為它能減少不必要的等待。如果你需要對時間做優(yōu)化,異步是一個很值得考慮的方案。
如果我們把同步與異步的概念遷移到網(wǎng)絡(luò)爬蟲的場景中,那我們之前學(xué)的爬蟲方式都是同步的。

爬蟲每發(fā)起一個請求,都要等服務(wù)器返回響應(yīng)后,才會執(zhí)行下一步。而很多時候,由于網(wǎng)絡(luò)不穩(wěn)定,加上服務(wù)器自身也需要響應(yīng)的時間,導(dǎo)致爬蟲會浪費大量時間在等待上。這也是爬取大量數(shù)據(jù)時,爬蟲的速度會比較慢的原因。
怎樣才能實現(xiàn)異步的爬蟲方式,提高爬蟲的效率呢?要回答這個問題的話,得了解一點點計算機的歷史小知識。

我們知道每臺計算機都靠著CPU(中央處理器)干活。在過去,單核CPU的計算機在處理多任務(wù)時,會出現(xiàn)一個問題:每個任務(wù)都要搶占CPU,執(zhí)行完了一個任務(wù)才開啟下一個任務(wù)。CPU畢竟只有一個,這會讓計算機處理的效率很低。

python爬蟲第11關(guān) 協(xié)程_第2張圖片
為了解決這樣的問題,一種非搶占式的異步技術(shù)被創(chuàng)造了出來,這種方式叫多協(xié)程(在此,多是多個的意思)。

它的原理是:一個任務(wù)在執(zhí)行過程中,如果遇到等待,就先去執(zhí)行其他的任務(wù),當?shù)却Y(jié)束,再回來繼續(xù)之前的那個任務(wù)。在計算機的世界,這種任務(wù)來回切換得非常快速,看上去就像多個任務(wù)在被同時執(zhí)行一樣。

這就好比當你要做一桌飯菜,你可以在等電飯煲蒸飯的時候去炒菜。而不是等飯做好,再去炒菜。你還是那個你,但工作時間就這樣被縮短了。多協(xié)程能夠縮短工作時間的原理,也是如此。

所以,要實現(xiàn)異步的爬蟲方式的話,需要用到多協(xié)程。在它的幫助下,我們能實現(xiàn)前面提到的“讓多個爬蟲替我們干活”。
那么,新的問題來了——怎么使用多協(xié)程?

多協(xié)程的用法

gevent庫
python爬蟲第11關(guān) 協(xié)程_第3張圖片
所以,接下來我會帶你了解gevent的用法,和實操一個多協(xié)程案例:爬取8個網(wǎng)站(包括百度、新浪、搜狐、騰訊、網(wǎng)易、愛奇藝、天貓、鳳凰)。

我們先用之前同步的爬蟲方式爬取這8個網(wǎng)站,然后等下再和gevent異步爬取做一個對比。

            
              import requests,time
#導(dǎo)入requests和time
start = time.time()
#記錄程序開始時間

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
#把8個網(wǎng)站封裝成列表

for url in url_list:
#遍歷url_list
    r = requests.get(url)
    #用requests.get()函數(shù)爬取網(wǎng)站
    print(url,r.status_code)
    #打印網(wǎng)址和抓取請求的狀態(tài)碼

end = time.time()
#記錄程序結(jié)束時間
print(end-start)
#end-start是結(jié)束時間減去開始時間,就是最終所花時間。
#最后,把時間打印出來。



            
          

python爬蟲第11關(guān) 協(xié)程_第4張圖片
程序運行后,你會看到同步的爬蟲方式,是依次爬取網(wǎng)站,并等待服務(wù)器響應(yīng)(狀態(tài)碼為200表示正常響應(yīng))后,才爬取下一個網(wǎng)站。比如第一個先爬取了百度的網(wǎng)址,等服務(wù)器響應(yīng)后,再去爬取新浪的網(wǎng)址,以此類推,直至全部爬取完畢。

為了讓你能更直觀地看到爬蟲完成任務(wù)所需的時間,我導(dǎo)入了time模塊,記錄了程序開始和結(jié)束的時間,最后打印出來的就是爬蟲爬取這8個網(wǎng)站所花費的時間。
如果我們用了多協(xié)程來爬取會有什么不同?

            
              from gevent import monkey
monkey.patch_all()
import gevent,time,requests

start = time.time()

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']

def crawler(url):
    r = requests.get(url)
    print(url,time.time()-start,r.status_code)

tasks_list = []

for url in url_list:
    task = gevent.spawn(crawler,url)
    tasks_list.append(task)
gevent.joinall(tasks_list)
end = time.time()
print(end-start)



            
          

python爬蟲第11關(guān) 協(xié)程_第5張圖片
通過每個請求運行的時間,我們能知道:爬蟲用了異步的方式抓取了8個網(wǎng)站,因為每個請求完成的時間并不是按著順序來的。比如在我測試運行這個代碼的時候,最先爬取到的網(wǎng)站是搜狐,接著是鳳凰,并不是百度和新浪。

且每個請求完成時間之間的間隔都非常短,你可以看作這些請求幾乎是“同時”發(fā)起的。

通過對比同步和異步爬取最終所花的時間,用多協(xié)程異步的爬取方式,確實比同步的爬蟲方式速度更快。
其實,我們案例爬取的數(shù)據(jù)量還比較小,不能直接體現(xiàn)出更大的速度差異。如果爬的是大量的數(shù)據(jù),運用多協(xié)程會有更顯著的速度優(yōu)勢。

比如我做了一個測試:把爬取8個網(wǎng)站變成爬取80個網(wǎng)站,用同步的爬取方式大概需要花17.3秒,但用多協(xié)程異步爬取只需大概4.5秒,整個爬取效率提升了280%+。
python爬蟲第11關(guān) 協(xié)程_第6張圖片
現(xiàn)在,我們一行行來看剛剛用了gevent的代碼。

提醒:導(dǎo)入gevent庫前,得先安裝它。(安裝方法:window電腦:在終端輸入命令:pip install gevent,按下enter鍵;mac電腦:在終端輸入命令:pip3 install gevent,按下enter鍵)
再來看一遍代碼:

            
              from gevent import monkey
#從gevent庫里導(dǎo)入monkey模塊。
monkey.patch_all()
#monkey.patch_all()能把程序變成協(xié)作式運行,就是可以幫助程序?qū)崿F(xiàn)異步。
import gevent,time,requests
#導(dǎo)入gevent、time、requests。

start = time.time()
#記錄程序開始時間。

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
#把8個網(wǎng)站封裝成列表。

def crawler(url):
#定義一個crawler()函數(shù)。
    r = requests.get(url)
    #用requests.get()函數(shù)爬取網(wǎng)站。
    print(url,time.time()-start,r.status_code)
    #打印網(wǎng)址、請求運行時間、狀態(tài)碼。

tasks_list = [ ]
#創(chuàng)建空的任務(wù)列表。

for url in url_list:
#遍歷url_list。
    task = gevent.spawn(crawler,url)
    #用gevent.spawn()函數(shù)創(chuàng)建任務(wù)。
    tasks_list.append(task)
    #往任務(wù)列表添加任務(wù)。
gevent.joinall(tasks_list)
#執(zhí)行任務(wù)列表里的所有任務(wù),就是讓爬蟲開始爬取網(wǎng)站。
end = time.time()
#記錄程序結(jié)束時間。
print(end-start)
#打印程序最終所需時間。



            
          

第1、3行代碼:從gevent庫里導(dǎo)入了monkey模塊,這個模塊能將程序轉(zhuǎn)換成可異步的程序。monkey.patch_all(),它的作用其實就像你的電腦有時會彈出“是否要用補丁修補漏洞或更新”一樣。它能給程序打上補丁,讓程序變成是異步模式,而不是同步模式。它也叫“猴子補丁”。
我們要在導(dǎo)入其他庫和模塊前,先把monkey模塊導(dǎo)入進來,并運行monkey.patch_all()。這樣,才能先給程序打上補丁。你也可以理解成這是一個規(guī)范的寫法。

第5行代碼:我們導(dǎo)入了gevent庫來幫我們實現(xiàn)多協(xié)程,導(dǎo)入了time模塊來幫我們記錄爬取所需時間,導(dǎo)入了requests模塊幫我們實現(xiàn)爬取8個網(wǎng)站。
python爬蟲第11關(guān) 協(xié)程_第7張圖片
第21、23、25行代碼:我們定義了一個crawler函數(shù),只要調(diào)用這個函數(shù),它就會執(zhí)行【用requests.get()爬取網(wǎng)站】和【打印網(wǎng)址、請求運行時間、狀態(tài)碼】這兩個任務(wù)。
python爬蟲第11關(guān) 協(xié)程_第8張圖片
第33行代碼:因為gevent只能處理gevent的任務(wù)對象,不能直接調(diào)用普通函數(shù),所以需要借助gevent.spawn()來創(chuàng)建任務(wù)對象。
這里需要注意一點:gevent.spawn()的參數(shù)需為要調(diào)用的函數(shù)名及該函數(shù)的參數(shù)。比如,gevent.spawn(crawler,url)就是創(chuàng)建一個執(zhí)行crawler函數(shù)的任務(wù),參數(shù)為crawler函數(shù)名和它自身的參數(shù)url。
python爬蟲第11關(guān) 協(xié)程_第9張圖片
第35行代碼:用append函數(shù)把任務(wù)添加到tasks_list的任務(wù)列表里。
第37行代碼:調(diào)用gevent庫里的joinall方法,能啟動執(zhí)行所有的任務(wù)。gevent.joinall(tasks_list)就是執(zhí)行tasks_list這個任務(wù)列表里的所有任務(wù),開始爬取。
python爬蟲第11關(guān) 協(xié)程_第10張圖片
總結(jié)一下用gevent實現(xiàn)多協(xié)程爬取的重點:
python爬蟲第11關(guān) 協(xié)程_第11張圖片
到這里,用gevent實操抓取8個網(wǎng)站我們已經(jīng)完成,gevent的基礎(chǔ)語法我們也大致了解。

那如果我們要爬的不是8個網(wǎng)站,而是1000個網(wǎng)站,我們可以怎么做?

用我們剛剛學(xué)的gevent語法,我們可以用gevent.spawn()創(chuàng)建1000個爬取任務(wù),再用gevent.joinall()執(zhí)行這1000個任務(wù)。

但這種方法會有問題:執(zhí)行1000個任務(wù),就是一下子發(fā)起1000次請求,這樣子的惡意請求,會拖垮網(wǎng)站的服務(wù)器。
python爬蟲第11關(guān) 協(xié)程_第12張圖片
既然這種直接創(chuàng)建1000個任務(wù)的方式不可取,那我們能不能只創(chuàng)建成5個任務(wù),但每個任務(wù)爬取200個網(wǎng)站?

假設(shè)我們有1000個任務(wù),那創(chuàng)建5個任務(wù),每個任務(wù)爬取200個網(wǎng)站的代碼可以寫成如下的樣子(此代碼僅做展示,并不可運行):

            
              from gevent import monkey
monkey.patch_all()
import gevent,time,requests

start = time.time()
url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/'
……
#假設(shè)有1000個網(wǎng)址
]

def crawler(url_list):
#定義一個crawler()函數(shù)。
    for url in url_list:
        r = requests.get(url)
        print(url,time.time()-start,r.status_code)

tasks_list = [ ]
#創(chuàng)建空的任務(wù)列表。
for i in range(5):
    task = gevent.spawn(crawler,url_list[i*200:(i+1)*200])
    #用gevent.spawn()函數(shù)創(chuàng)建5個任務(wù)。
    tasks_list.append(task)
    #往任務(wù)列表添加任務(wù)。

gevent.joinall(tasks_list)
end = time.time()
print(end-start)



            
          

遺憾地告訴你,這么做也還是會有問題的。就算我們用gevent.spawn()創(chuàng)建了5個分別執(zhí)行爬取200個網(wǎng)站的任務(wù),這5個任務(wù)之間是異步執(zhí)行的,但是每個任務(wù)(爬取200個網(wǎng)站)內(nèi)部是同步的。
這意味著:如果有一個任務(wù)在執(zhí)行的過程中,它要爬取的一個網(wǎng)站一直在等待響應(yīng),哪怕其他任務(wù)都完成了200個網(wǎng)站的爬取,它也還是不能完成200個網(wǎng)站的爬取。
python爬蟲第11關(guān) 協(xié)程_第13張圖片
這個方法也不行,那還有什么方法呢?

這時我們可以從實際生活的案例中得到啟發(fā)。想想銀行是怎么在一天內(nèi)辦理1000個客戶的業(yè)務(wù)的。

銀行會開設(shè)辦理業(yè)務(wù)的多個窗口,讓客戶取號排隊,由銀行的叫號系統(tǒng)分配客戶到不同的窗口去辦理業(yè)務(wù)。

在gevent庫中,也有一個模塊可以實現(xiàn)這種功能——queue模塊。

queue模塊
當我們用多協(xié)程來爬蟲,需要創(chuàng)建大量任務(wù)時,我們可以借助queue模塊。

queue翻譯成中文是隊列的意思。我們可以用queue模塊來存儲任務(wù),讓任務(wù)都變成一條整齊的隊列,就像銀行窗口的排號做法。因為queue其實是一種有序的數(shù)據(jù)結(jié)構(gòu),可以用來存取數(shù)據(jù)。

這樣,協(xié)程就可以從隊列里把任務(wù)提取出來執(zhí)行,直到隊列空了,任務(wù)也就處理完了。就像銀行窗口的工作人員會根據(jù)排號系統(tǒng)里的排號,處理客人的業(yè)務(wù),如果已經(jīng)沒有新的排號,就意味著客戶的業(yè)務(wù)都已辦理完畢。
python爬蟲第11關(guān) 協(xié)程_第14張圖片
接下來,我們來實操看看,可以怎么用queue模塊和協(xié)程配合,依舊以抓取8個網(wǎng)站為例。

            
              from gevent import monkey
monkey.patch_all()
import gevent,time,requests
from gevent.queue import Queue

start = time.time()

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']

work = Queue()
for url in url_list:
    work.put_nowait(url)

def crawler():
    while not work.empty():
        url = work.get_nowait()
        r = requests.get(url)
        print(url,work.qsize(),r.status_code)

tasks_list  = [ ]

for x in range(2):
    task = gevent.spawn(crawler)
    tasks_list.append(task)
gevent.joinall(tasks_list)

end = time.time()
print(end-start)



            
          

python爬蟲第11關(guān) 協(xié)程_第15張圖片
網(wǎng)址后面的數(shù)字指的是隊列里還剩的任務(wù)數(shù),比如第一個網(wǎng)址后面的數(shù)字6,就是此時隊列里還剩6個抓取其他網(wǎng)址的任務(wù)。

現(xiàn)在,我們把剛剛運行的代碼拆成4部分來講解,第1部分是導(dǎo)入模塊。

            
              from gevent import monkey
#從gevent庫里導(dǎo)入monkey模塊。
monkey.patch_all()
#monkey.patch_all()能把程序變成協(xié)作式運行,就是可以幫助程序?qū)崿F(xiàn)異步。
import gevent,time,requests
#導(dǎo)入gevent、time、requests
from gevent.queue import Queue
#從gevent庫里導(dǎo)入queue模塊


            
          

因為gevent庫里就帶有queue,所以我們用【from gevent.queue import Queue】就能把queue模塊導(dǎo)入。其他模塊和代碼我們在講解gevent時已經(jīng)講解過了,相信你能懂。

第2部分,是如何創(chuàng)建隊列,以及怎么把任務(wù)存儲進隊列里。

            
              start = time.time()
#記錄程序開始時間

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']

work = Queue()
#創(chuàng)建隊列對象,并賦值給work。
for url in url_list:
#遍歷url_list
    work.put_nowait(url)
    #用put_nowait()函數(shù)可以把網(wǎng)址都放進隊列里。



            
          

用Queue()能創(chuàng)建queue對象,相當于創(chuàng)建了一個不限任何存儲數(shù)量的空隊列。如果我們往Queue()中傳入?yún)?shù),比如Queue(10),則表示這個隊列只能存儲10個任務(wù)。

創(chuàng)建了queue對象后,我們就能調(diào)用這個對象的put_nowait方法,把我們的每個網(wǎng)址都存儲進我們剛剛建立好的空隊列里。

work.put_nowait(url)這行代碼就是把遍歷的8個網(wǎng)站,都存儲進隊列里。

第3部分,是定義爬取函數(shù),和如何從隊列里提取出剛剛存儲進去的網(wǎng)址。

            
              def crawler():
    while not work.empty():
    #當隊列不是空的時候,就執(zhí)行下面的程序。
        url = work.get_nowait()
        #用get_nowait()函數(shù)可以把隊列里的網(wǎng)址都取出。
        r = requests.get(url)
        #用requests.get()函數(shù)抓取網(wǎng)址。
        print(url,work.qsize(),r.status_code)
        #打印網(wǎng)址、隊列長度、抓取請求的狀態(tài)碼。



            
          

這里定義的crawler函數(shù),多了三個你可能看不懂的代碼:1.while not work.empty():;2.url = work.get_nowait();3.work.qsize()。

這三個代碼涉及到queue對象的三個方法:empty方法,是用來判斷隊列是不是空了的;get_nowait方法,是用來從隊列里提取數(shù)據(jù)的;qsize方法,是用來判斷隊列里還剩多少數(shù)量的。

當然,queue對象的方法還不止這幾種,比如有判斷隊列是否為空的empty方法,對應(yīng)也有判斷隊列是否為滿的full方法。

你是不是覺得queue對象這么多方法,一下子記不住?其實,這些不需要你死記硬背的,附上一張queue對象的方法表,你只需要在用到的時候,查查表就好。
python爬蟲第11關(guān) 協(xié)程_第16張圖片
代碼的前3部分,我們講解完了。如果你能明白隊列怎么創(chuàng)建、數(shù)據(jù)怎么存儲進隊列,以及怎么從隊列里提取出的數(shù)據(jù),就說明queue模塊的重點內(nèi)容你都掌握了。

python爬蟲第11關(guān) 協(xié)程_第17張圖片
接在第3部分代碼的后面,就是讓爬蟲用多協(xié)程執(zhí)行任務(wù),爬取隊列里的8個網(wǎng)站的代碼(重點看有注釋的代碼)。

            
              def crawler():
    while not work.empty():
        url = work.get_nowait()
        r = requests.get(url)
        print(url,work.qsize(),r.status_code)

tasks_list  = [ ]
#創(chuàng)建空的任務(wù)列表
for x in range(2):
#相當于創(chuàng)建了2個爬蟲
    task = gevent.spawn(crawler)
    #用gevent.spawn()函數(shù)創(chuàng)建執(zhí)行crawler()函數(shù)的任務(wù)。
    tasks_list.append(task)
    #往任務(wù)列表添加任務(wù)。
gevent.joinall(tasks_list)
#用gevent.joinall方法,執(zhí)行任務(wù)列表里的所有任務(wù),就是讓爬蟲開始爬取網(wǎng)站。
end = time.time()
print(end-start)



            
          

python爬蟲第11關(guān) 協(xié)程_第18張圖片
我們創(chuàng)建了兩只可以異步爬取的爬蟲。它們會從隊列里取走網(wǎng)址,執(zhí)行爬取任務(wù)。一旦一個網(wǎng)址被一只爬蟲取走,另一只爬蟲就取不到了,另一只爬蟲就會取走下一個網(wǎng)址。直至所有網(wǎng)址都被取走,隊列為空時,爬蟲就停止工作。

用協(xié)程技術(shù)和隊列爬取8個網(wǎng)站的完整代碼如下:

            
              from gevent import monkey#gevent從庫里導(dǎo)入monkey模塊
monkey.patch_all()#能把程序變成協(xié)作式運行,就是可以幫助程序?qū)崿F(xiàn)異步
import gevent,time,requests
from gevent.queue import Queue#gevent從庫里導(dǎo)入queue模塊

start=time.time()

url_list=['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/'
]

work=Queue()#創(chuàng)建隊列對象,并賦值給work

for url in url_list:
    work.put_nowait(url)#用put_nowait()函數(shù)可以把網(wǎng)址都放進隊列里。

def crawler():
    while not work.empty():#當隊列不是空的時候,就執(zhí)行下面的程序
        url=work.get_nowait()#get_nowait()函數(shù)可以把隊列里的網(wǎng)址都取出。
        res=requests.get(url)#用requests.get()函數(shù)抓取網(wǎng)址。
        print(url,work.qsize(),res.status_code)#打印網(wǎng)址、隊列長度、抓取請求的狀態(tài)碼

tasks_list=[]#創(chuàng)建空的任務(wù)列表

for x in range(2):#相當于創(chuàng)建了兩個爬蟲
    task=gevent.spawn(crawler)#用gevent.spawn()函數(shù)創(chuàng)建執(zhí)行crawler()函數(shù)的任務(wù)
    tasks_list.append(task)

gevent.joinall(tasks_list)#用gevent.joinall方法,執(zhí)行任務(wù)列表里的所有任務(wù),就是讓爬蟲開始爬取網(wǎng)站。

end=time.time()
print(end-start)



            
          

動手總會有收獲的。恭喜你,這一關(guān)的核心知識,實現(xiàn)多協(xié)程的gevent庫和Queue模塊,你都學(xué)完了!

拓展復(fù)習

不過,我還想和你拓展一點新的知識。

同樣是要做飯菜,我們已經(jīng)知道比先做飯再做菜更好的方式是,等待做飯的過程中去做菜。但其實還有更快的方案:讓一個人負責做飯,一個人負責做菜。

繼續(xù)說我們的計算機歷史小知識:在后來,我們的CPU從單核終于進化到了多核,每個核都能夠獨立運作。計算機開始能夠真正意義上同時執(zhí)行多個任務(wù)(術(shù)語叫并行執(zhí)行),而不是在多個任務(wù)之間來回切換(術(shù)語叫并發(fā)執(zhí)行)。

比如你現(xiàn)在打開瀏覽器看著爬蟲課程的同時,可以打開音樂播放器聽歌,還可以打開Excel。對于多核CPU而言,這些任務(wù)就都是同時運行的。

時至今日,我們電腦一般都會是多核CPU。多協(xié)程,其實只占用了CPU的一個核運行,沒有充分利用到其他核。利用CPU的多個核同時執(zhí)行任務(wù)的技術(shù),我們把它叫做“多進程”。

所以,真正大型的爬蟲程序不會單單只靠多協(xié)程來提升爬取速度的。比如,百度搜索引擎,可以說是超大型的爬蟲程序,它除了靠多協(xié)程,一定還會靠多進程,甚至是分布式爬蟲。

多進程爬蟲和分布式爬蟲不屬于我們這個課程的知識范疇,我這里不會多講?;蛟S接下來我們會開設(shè)爬蟲進階課程,到時再和大家分享。

最后,是這一關(guān)的復(fù)習。
同步與異步——
python爬蟲第11關(guān) 協(xié)程_第19張圖片
多協(xié)程,是一種非搶占式的異步方式。使用多協(xié)程的話,就能讓多個爬取任務(wù)用異步的方式交替執(zhí)行。
python爬蟲第11關(guān) 協(xié)程_第20張圖片
python爬蟲第11關(guān) 協(xié)程_第21張圖片
python爬蟲第11關(guān) 協(xié)程_第22張圖片
python爬蟲第11關(guān) 協(xié)程_第23張圖片
python爬蟲第11關(guān) 協(xié)程_第24張圖片


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論