網路爬蟲是一種高io密集型任務,所以傳統的程序或者多程序並不適合網路爬蟲。雖然由於cpython中全域性直譯器鎖gil的存在,無法真正意義上的實現多執行緒,但這種「不完美的多執行緒」依然可以大大提高爬蟲效率,當然在提高爬蟲效率方面還有大家所熟知的協程。
比較官方的介紹我就不說了,畢竟瞅了一眼一大串,這個快節奏的時代相信也沒有多少人看到下去,哈哈。
簡單的講,如果把乙個程序看成乙個空間,那麼多程序就是多個可以互相隔離的並行空間,而多執行緒則是在乙個程序空間中開闢出多個並行的執行緒,這也就意味著多個執行緒間是共享資源的,因此多執行緒相比於多程序的資料安全性更低,這也是cpython引入gil的原因。那麼如何理解協程呢,事實上,多執行緒的本質是在乙個程序的基礎上實現高併發,而協程則是在乙個執行緒的基礎上實現高併發,協程的排程是通過**來實現的,而不是cpu。(還是寫了一大串哈)
from gevent import monkey;monkey.patch_all()
from lxml import etree
from concurrent.futures import threadpoolexecutor
import requests
import time
import gevent
"""設定乙個計算函式執行時間的裝飾器"""
"""實現單程序/單執行緒爬蟲類
"""繼承自父類baiduspider,實現多執行緒
"""def __init__(self):
super().__init__()
self.tpool = threadpoolexecutor(max_workers=20) # 設定執行緒池中允許通過的執行緒數量
"""繼承自父類baiduspider,實現多協程
"""def __init__(self):
super().__init__()
def run(self, page):
a_list =
for i in range(page):
pn = i * 10
g = gevent.spawn(self.schedule, pn)
for i in a_list:
i.join()
if __name__ == '__main__':
# a = baiduspider() # 單程序/單執行緒當前用時3.900386333465576
# a.run(6)
# b = threadbaidu() # 多執行緒當前用時0.8708631992340088
# b.run(6)
c = asyncbaidu() # 多協程當前用時0.8858425617218018
c.run(6)
協程與執行緒
reference 協程不只在go語言中實現了,其實目前大部分語言都實現了自己的一套協程,包括c erlang python lua j ascript ruby等。相對於協程,你可能對程序和執行緒更為熟悉。程序一般代表乙個應用服務,在乙個應用服務中可以建立多個執行緒,而協程與程序 執行緒的概念不一...
協程的多執行緒切換
我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住...
協程的多執行緒切換
我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住...