Python并发爬虫常用实现方法解析

时间:2021-05-22

在进行单个爬虫抓取的时候,我们不可能按照一次抓取一个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:///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)

抓取的时间如下:

可以看到总共花费了128087秒,而这所花费的时间恰恰就是最后一个url抓取所需要的时间,tornado中自带了查看每个请求的相应时间。我们可以从图中看到,最后一个url抓取总共花了1.28087秒,相较于其他时间大大的增加,这也是导致我们消耗时间过长的原因。那可以推断出,前面的并发抓取,也在这个url上花费了较多的时间。

总结:

以上测试其实非常的不严谨,因为我们选取的url的数量太少了,完全不能反映每一种抓取方式的优劣。如果有一万个不同的url同时抓取,那么记下总抓取时间,是可以得出一个较为客观的结果的。

并且,已经有人测试过,多线程抓取的效率是远不如gevent的。所以,如果你使用的是python2,那么我推荐你使用gevent进行并发抓取;如果你使用的是python3,我推荐你使用tornado的http客户端结合coroutine进行并发抓取。从上面的结果来看,tornado的coroutine是高于gevent的轻量级的协程的。但具体结果怎样,我没测试过。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章