电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Python并發爬蟲常用實現方法解析

瀏覽:2日期:2022-07-04 18:17:43

在進行單個爬蟲抓取的時候,我們不可能按照一次抓取一個url的方式進行網頁抓取,這樣效率低,也浪費了cpu的資源。目前python上面進行并發抓取的實現方式主要有以下幾種:進程,線程,協程。進程不在的討論范圍之內,一般來說,進程是用來開啟多個spider,比如我們開啟了4進程,同時派發4個spider進行網絡抓取,每個spider同時抓取4個url。

所以,我們今天討論的是,在單個爬蟲的情況下,盡可能的在同一個時間并發抓取,并且抓取的效率要高。

一.順序抓取

順序抓取是最最常見的抓取方式,一般初學爬蟲的朋友就是利用這種方式,下面是一個測試代碼,順序抓取8個url,我們可以來測試一下抓取完成需要多少時間:

HEADERS = {’Accept’: ’text/html,application/xhtml+xml,application/xml;q=0.9’, ’Accept-Language’: ’zh-CN,zh;q=0.8’, ’Accept-Encoding’: ’gzip, deflate’,} URLS = [’http://www.cnblogs.com/moodlxs/p/3248890.html’, ’https://www.zhihu.com/topic/19804387/newest’,’http://blog.csdn.net/yueguanghaidao/article/details/24281751’,’https://my.oschina.net/visualgui823/blog/36987’, ’http://blog.chinaunix.net/uid-9162199-id-4738168.html’, ’http://www.tuicool.com/articles/u67Bz26’, ’http://rfyiamcool.blog.51cto.com/1030776/1538367/’, ’http://itindex.net/detail/26512-flask-tornado-gevent’] #url為隨機獲取的一批url def func(): ''' 順序抓取 ''' import requestsimport time urls = URLS headers = HEADERS headers[’user-agent’] = 'Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537' '.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36' print(u’順序抓取’)starttime= time.time() for url in urls: try: r = requests.get(url, allow_redirects=False, timeout=2.0, headers=headers)except: pass else: print(r.status_code, r.url) endtime=time.time() print(endtime-starttime) func()

我們直接采用內建的time.time()來計時,較為粗略,但可以反映大概的情況。下面是順序抓取的結果計時:

Python并發爬蟲常用實現方法解析

可以從圖片中看到,顯示的順序與urls的順序是一模一樣的,總共耗時為7.763269901275635秒,一共8個url,平均抓取一個大概需要0.97秒。總體來看,還可以接受。

二.多線程抓取

線程是python內的一種較為不錯的并發方式,我們也給出相應的代碼,并且為每個url創建了一個線程,一共8線程并發抓取,下面的代碼:

下面是我們運行8線程的測試代碼:

HEADERS = {’Accept’: ’text/html,application/xhtml+xml,application/xml;q=0.9’, ’Accept-Language’: ’zh-CN,zh;q=0.8’, ’Accept-Encoding’: ’gzip, deflate’,} URLS = [’http://www.cnblogs.com/moodlxs/p/3248890.html’, ’https://www.zhihu.com/topic/19804387/newest’, ’http://blog.csdn.net/yueguanghaidao/article/details/24281751’, ’https://my.oschina.net/visualgui823/blog/36987’, ’http://blog.chinaunix.net/uid-9162199-id-4738168.html’, ’http://www.tuicool.com/articles/u67Bz26’, ’http://rfyiamcool.blog.51cto.com/1030776/1538367/’, ’http://itindex.net/detail/26512-flask-tornado-gevent’]def thread(): from threading import Threadimport requests import timeurls = URLSheaders = HEADERS headers[’user-agent’] = 'Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+' '(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36' def get(url): try: r = requests.get(url, allow_redirects=False, timeout=2.0, headers=headers) except:pass else: print(r.status_code, r.url) print(u’多線程抓取’) ts = [Thread(target=get, args=(url,)) for url in urls] starttime= time.time() for t in ts: t.start() for t in ts: t.join()endtime=time.time() print(endtime-starttime)thread()

多線程抓住的時間如下:

Python并發爬蟲常用實現方法解析

可以看到相較于順序抓取,8線程的抓取效率明顯上升了3倍多,全部完成只消耗了2.154秒。可以看到顯示的結果已經不是urls的順序了,說明每個url各自完成的時間都是不一樣的。線程就是在一個進程中不斷的切換,讓每個線程各自運行一會,這對于網絡io來說,性能是非常高的。但是線程之間的切換是挺浪費資源的。

三.gevent并發抓取

gevent是一種輕量級的協程,可用它來代替線程,而且,他是在一個線程中運行,機器資源的損耗比線程低很多。如果遇到了網絡io阻塞,會馬上切換到另一個程序中去運行,不斷的輪詢,來降低抓取的時間 下面是測試代碼:

HEADERS = {’Accept’: ’text/html,application/xhtml+xml,application/xml;q=0.9’, ’Accept-Language’: ’zh-CN,zh;q=0.8’, ’Accept-Encoding’: ’gzip, deflate’,}URLS = [’http://www.cnblogs.com/moodlxs/p/3248890.html’, ’https://www.zhihu.com/topic/19804387/newest’, ’http://blog.csdn.net/yueguanghaidao/article/details/24281751’, ’https://my.oschina.net/visualgui823/blog/36987’, ’http://blog.chinaunix.net/uid-9162199-id-4738168.html’, ’http://www.tuicool.com/articles/u67Bz26’, ’http://rfyiamcool.blog.51cto.com/1030776/1538367/’, ’http://itindex.net/detail/26512-flask-tornado-gevent’]def main(): ''' gevent并發抓取 ''' import requests import gevent import time headers = HEADERS headers[’user-agent’] = 'Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+' '(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36' urls = URLS def get(url): try: r = requests.get(url, allow_redirects=False, timeout=2.0, headers=headers) except: pass else: print(r.status_code, r.url) print(u’基于gevent的并發抓取’) starttime= time.time() g = [gevent.spawn(get, url) for url in urls] gevent.joinall(g) endtime=time.time() print(endtime - starttime)main()

協程的抓取時間如下:

Python并發爬蟲常用實現方法解析

正常情況下,gevent的并發抓取與多線程的消耗時間差不了多少,但是可能是我網絡的原因,或者機器的性能的原因,時間有點長......,請各位小主在自己電腦進行跑一下看運行時間

四.基于tornado的coroutine并發抓取

tornado中的coroutine是python中真正意義上的協程,與python3中的asyncio幾乎是完全一樣的,而且兩者之間的future是可以相互轉換的,tornado中有與asyncio相兼容的接口。 下面是利用tornado中的coroutine進行并發抓取的代碼:

利用coroutine編寫并發略顯復雜,但這是推薦的寫法,如果你使用的是python3,強烈建議你使用coroutine來編寫并發抓取。

下面是測試代碼:

HEADERS = {’Accept’: ’text/html,application/xhtml+xml,application/xml;q=0.9’, ’Accept-Language’: ’zh-CN,zh;q=0.8’, ’Accept-Encoding’: ’gzip, deflate’,}URLS = [’http://www.cnblogs.com/moodlxs/p/3248890.html’, ’https://www.zhihu.com/topic/19804387/newest’, ’http://blog.csdn.net/yueguanghaidao/article/details/24281751’, ’https://my.oschina.net/visualgui823/blog/36987’, ’http://blog.chinaunix.net/uid-9162199-id-4738168.html’, ’http://www.tuicool.com/articles/u67Bz26’, ’http://rfyiamcool.blog.51cto.com/1030776/1538367/’, ’http://itindex.net/detail/26512-flask-tornado-gevent’]import timefrom tornado.gen import coroutinefrom tornado.ioloop import IOLoopfrom tornado.httpclient import AsyncHTTPClient, HTTPErrorfrom tornado.httpclient import HTTPRequest#urls與前面相同class MyClass(object): def __init__(self): #AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient') self.http = AsyncHTTPClient() @coroutine def get(self, url): #tornado會自動在請求首部帶上host首部 request = HTTPRequest(url=url, method=’GET’, headers=HEADERS, connect_timeout=2.0, request_timeout=2.0, follow_redirects=False, max_redirects=False, user_agent='Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+ (KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36',) yield self.http.fetch(request, callback=self.find, raise_error=False) def find(self, response): if response.error: print(response.error) print(response.code, response.effective_url, response.request_time)class Download(object): def __init__(self): self.a = MyClass() self.urls = URLS @coroutine def d(self): print(u’基于tornado的并發抓取’) starttime = time.time() yield [self.a.get(url) for url in self.urls] endtime=time.time() print(endtime-starttime)if __name__ == ’__main__’: dd = Download() loop = IOLoop.current() loop.run_sync(dd.d)

抓取的時間如下:

Python并發爬蟲常用實現方法解析

可以看到總共花費了128087秒,而這所花費的時間恰恰就是最后一個url抓取所需要的時間,tornado中自帶了查看每個請求的相應時間。我們可以從圖中看到,最后一個url抓取總共花了1.28087秒,相較于其他時間大大的增加,這也是導致我們消耗時間過長的原因。那可以推斷出,前面的并發抓取,也在這個url上花費了較多的時間。

總結:

以上測試其實非常的不嚴謹,因為我們選取的url的數量太少了,完全不能反映每一種抓取方式的優劣。如果有一萬個不同的url同時抓取,那么記下總抓取時間,是可以得出一個較為客觀的結果的。

并且,已經有人測試過,多線程抓取的效率是遠不如gevent的。所以,如果你使用的是python2,那么我推薦你使用gevent進行并發抓取;如果你使用的是python3,我推薦你使用tornado的http客戶端結合coroutine進行并發抓取。從上面的結果來看,tornado的coroutine是高于gevent的輕量級的協程的。但具體結果怎樣,我沒測試過。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 膏剂灌装旋盖机-眼药水灌装生产线-西林瓶粉剂分装机-南通博琅机械科技 | 散热器-电子散热器-型材散热器-电源散热片-镇江新区宏图电子散热片厂家 | 劳动法网-专业的劳动法和劳动争议仲裁服务网 | 涿州网站建设_网站设计_网站制作_做网站_固安良言多米网络公司 | SPC工作站-连杆综合检具-表盘气动量仪-内孔缺陷检测仪-杭州朗多检测仪器有限公司 | 铝箔袋,铝箔袋厂家,东莞铝箔袋,防静电铝箔袋,防静电屏蔽袋,防静电真空袋,真空袋-东莞铭晋让您的产品与众不同 | 钢格板|镀锌钢格板|热镀锌钢格板|格栅板|钢格板|钢格栅板|热浸锌钢格板|平台钢格板|镀锌钢格栅板|热镀锌钢格栅板|平台钢格栅板|不锈钢钢格栅板 - 专业钢格板厂家 | 申江储气罐厂家,储气罐批发价格,储气罐规格-上海申江压力容器有限公司(厂) | 一体化污水处理设备-一体化净水设备-「山东梦之洁水处理」 | 裹包机|裹膜机|缠膜机|绕膜机-上海晏陵智能设备有限公司 | 阿尔法-MDR2000无转子硫化仪-STM566 SATRA拉力试验机-青岛阿尔法仪器有限公司 | 牛奶检测仪-乳成分分析仪-北京海谊| 青岛空压机,青岛空压机维修/保养,青岛空压机销售/出租公司,青岛空压机厂家电话 | 水厂自动化-水厂控制系统-泵站自动化|控制系统-闸门自动化控制-济南华通中控科技有限公司 | 领先的大模型技术与应用公司-中关村科金 | 耳模扫描仪-定制耳机设计软件-DLP打印机-asiga打印机-fitshape「飞特西普」 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 空冷器|空气冷却器|空水冷却器-无锡赛迪森机械有限公司[官网] | 防水套管_柔性防水套管_刚性防水套管-巩义市润达管道设备制造有限公司 | 江苏远邦专注皮带秤,高精度皮带秤,电子皮带秤研发生产 | 玻璃钢罐_玻璃钢储罐_盐酸罐厂家-河北华盛节能设备有限公司 | 成都竞价托管_抖音代运营_网站建设_成都SEM外包-成都智网创联网络科技有限公司 | 广域铭岛Geega(际嘉)工业互联网平台-以数字科技引领行业跃迁 | 蓄电池回收,ups电池后备电源回收,铅酸蓄电池回收,机房电源回收-广州益夫铅酸电池回收公司 | 汝成内控-行政事业单位内部控制管理服务商| 坏男孩影院-提供最新电影_动漫_综艺_电视剧_迅雷免费电影最新观看 | 电力电子产业网| 右手官网|右手工业设计|外观设计公司|工业设计公司|产品创新设计|医疗产品结构设计|EMC产品结构设计 | 贵州自考_贵州自学考试网 | 武汉印刷厂-不干胶标签印刷厂-武汉不干胶印刷-武汉标签印刷厂-武汉标签制作 - 善进特种标签印刷厂 | 复合土工膜厂家|hdpe防渗土工膜|复合防渗土工布|玻璃纤维|双向塑料土工格栅-安徽路建新材料有限公司 | 铝镁锰板_铝镁锰合金板_铝镁锰板厂家_铝镁锰金属屋面板_安徽建科 | 艾乐贝拉细胞研究中心 | 国家组织工程种子细胞库华南分库 | 铜镍-康铜-锰铜-电阻合金-NC003 - 杭州兴宇合金有限公司 | 深圳3D打印服务-3D打印加工-手板模型加工厂-悟空打印坊 | 室内室外厚型|超薄型|非膨胀型钢结构防火涂料_隧道专用防火涂料厂家|电话|价格|批发|施工 | 苏州西朗门业-欧盟CE|莱茵UL双认证的快速卷帘门品牌厂家 | ICP备案查询_APP备案查询_小程序备案查询 - 备案巴巴 | R507制冷剂,R22/R152a制冷剂厂家-浙江瀚凯制冷科技有限公司 | 自进式锚杆-自钻式中空注浆锚杆-洛阳恒诺锚固锚杆生产厂家 | 郑州宣传片拍摄-TVC广告片拍摄-微电影短视频制作-河南优柿文化传媒有限公司 |