2017-04-22 85 views
0

我从数千个网页获取更新。可以有多个具有相同域的页面。我已将DOWNLOAD_DELAY设置为1秒,所以我不会超载服务器。如何更改Scrapy蜘蛛网站的订单?

蜘蛛效果很好,但是如果有100个相同域名的网站彼此相邻,它会减慢爬行速度,因为蜘蛛必须在每次请求后等待1秒。

是否有可能使其抓取具有不同域名的下一个网址,因此Spider无需等待?

例如:

CONCURRENT_REQUESTS = 3 
DOWNLOAD_DELAY = 1 

URLS:A.com/1,A.com/2,A.com/3,A.com/4,B.com/1,B.com/2,B.com/3

蜘蛛将开始抢先前三个网址。由于下载延迟,它至少需要三秒钟的时间。但如果它处理了B.com/1而不是A.com/2(例如),它会更快。

class MainSpider(scrapy.Spider): 
    ... 

    def __init__(self, scraping_round, frequencies=None): 
     super(MainSpider, self).__init__()) 
     ... 

    def start_requests(self): 
     for url in self.urls: 
      yield scrapy.Request(url=url, callback=self.parse, errback=self.err, dont_filter=True) 

也许我应该重新订购urls列表。

回答

1

肯定是,重排排序请求列表将有所帮助。可以做这样的:随后创建的,而爬行是比较困难的,不幸的是,但也许这已经帮助

import random 

class MainSpider(scrapy.Spider): 
    # .... 

    def start_requests(self): 
     random.shuffle(self.urls) 
     for url in self.urls: 
      yield scrapy.Request(url=url, callback=self.parse, errback=self.err, dont_filter=True) 

重新排序的请求。

另一个修正:大量增加CONCURRENT_REQUESTS。

的scrapy文档建议至少要100设置CONCURRENT_REQUESTS如果你想抓取多种领域并行:基于

https://doc.scrapy.org/en/latest/topics/broad-crawls.html#increase-concurrency

这样做的原因/详细解释

源代码scrapy/core/downloader.py, engine.py, scraper.py and scrapy/core/downloader/handlers/http11.py似乎scrapy会用调度程序中的CONCURRENT_REQUESTS填充其处理队列,并检查域以观察CONCURRENT_REQUESTS_PER_DOMAIN后面的过程唱连锁。

如果调度程序在一行中包含一堆针对同一个域的请求,则可能会有多个请求将同一个域拉入处理队列,从而有效阻止处理其他域。如果CONCURRENT_REQUESTS非常低,这很可能发生在您的示例中。

这是这里所描述的一个已知问题:https://github.com/scrapy/scrapy/issues/2474

替代方案

比CONCURRENT_REQUESTS提高到一个很高的值甚至更好的解决办法是使用https://github.com/scrapinghub/frontera作为爬行前沿......这是基本上按照您的建议进行:重新排序优化处理的计划请求。

+0

谢谢你的答案。我已经把并发请求设置为100,但在问题中是3作为一个简单的例子。但我可以从列表中的相同域相邻的2000个URL,因此100对我无能为力。我可能会随机排队或按域分组。弗隆特拉看起来不错,但这不是矫枉过正吗?或者,如果你愿意,你可以在这里张贴一个与frontera和我的蜘蛛的例子吗? –

+0

是的,如果你有来自同一个域的那么多网址,它们会帮助你很多的随机化。在您的URL列表中调用'random.shuffle'应该可以做到这一点(https://docs.python.org/2/library/random.html#random.shuffle)。 – rrschmidt

+0

Frontera将有助于排除最后一点的并行性,但是随机化列表对于您的目的而言是足够的。 – rrschmidt

0

DOWNLOAD_DELAY设置每个网站应用。

下载器在从同一网站下载连续页面之前应等待的时间量(以秒为单位)。这可以用来限制爬网速度,以避免太大的打击服务器。

从文档:https://doc.scrapy.org/en/latest/topics/settings.html#download-delay

所以,你想应该是默认的工作是什么。当蜘蛛启动时,它立即排队start_urls中的每个url,然后对延迟进行排序等。

+0

好吧,如果我明白了:如果网址列表是A.com/1,A.com/2,A,com/3,A.com/4,B.com/1,B.com/2和CONCURENT_REQUESTS = 3和DOWNLOAD_DELAY = 1,它应以A.com/1和B.com/1“平行”开始,然后在一秒后A.com/2 + B.com/2开始。这是真的吗?我不想等到A.com被抓取后才抓取B.com。 –

+0

是的,A.com和B.com将没有共享延迟,因此他们会一起参与游戏。 – Granitosaurus

+0

不,它不会。 A.com/1,A.com/2,A.com/3将填满所有3个处理插槽,因为它们将首先从计划程序中拔出。另请参阅我的答案。这是一个已知问题:https://github.com/scrapy/scrapy/issues/2474 – rrschmidt