Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Scrapy spider中更改URL顺序?_Python_Python 2.7_Scrapy_Web Crawler - Fatal编程技术网

Python 如何在Scrapy spider中更改URL顺序?

Python 如何在Scrapy spider中更改URL顺序?,python,python-2.7,scrapy,web-crawler,Python,Python 2.7,Scrapy,Web Crawler,我从成千上万的网页上得到更新。同一域中可以有多个页面。我已经将下载延迟设置为1秒,这样我就不会使服务器过载 Spider工作得很好,但如果同一个域的100个URL彼此相邻,则会减慢爬行速度,因为Spider必须在每个请求后等待1秒 有没有可能让它抓取下一个不同域的URL,这样蜘蛛就不必等待了 例如: CONCURRENT_REQUESTS = 3 DOWNLOAD_DELAY = 1 网址:A.com/1、A.com/2、A.com/3、A.com/4、B.com/1、B.com/2、B.co

我从成千上万的网页上得到更新。同一域中可以有多个页面。我已经将下载延迟设置为1秒,这样我就不会使服务器过载

Spider工作得很好,但如果同一个域的100个URL彼此相邻,则会减慢爬行速度,因为Spider必须在每个请求后等待1秒

有没有可能让它抓取下一个不同域的URL,这样蜘蛛就不必等待了

例如:

CONCURRENT_REQUESTS = 3
DOWNLOAD_DELAY = 1
网址:A.com/1、A.com/2、A.com/3、A.com/4、B.com/1、B.com/2、B.com/3

蜘蛛将开始抓取前三个URL。由于下载延迟,至少需要3秒钟。但如果它处理的是B.com/1而不是A.com/2(例如),则速度会更快


也许我应该重新排列
URL
列表。

下载延迟
设置适用于每个网站

下载程序从同一网站下载连续页面之前应等待的时间(秒)。这可以用来限制爬行速度,以避免对服务器造成太大的冲击

从文档:


因此,默认情况下,您想要的应该可以工作。当spider启动时,它会立即将每个url排列在
start\u url
中,然后对延迟进行排序等。

DOWNLOAD\u delay
设置适用于每个网站

下载程序从同一网站下载连续页面之前应等待的时间(秒)。这可以用来限制爬行速度,以避免对服务器造成太大的冲击

从文档:


因此,默认情况下,您想要的应该可以工作。当spider启动时,它会立即在
start\u url
中对每个url进行排队,然后对延迟进行排序等。

当然是,重新排序计划请求列表会有所帮助。可以这样做:

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)
不幸的是,对随后在爬网时创建的请求进行重新排序更加困难,但这可能已经有所帮助

另一个修复方法:大量增加并发请求

scrapy文档建议,如果要并行爬网多个域,则至少将并发_请求设置为100:

原因/详细解释

基于
scrapy/core/downloader.py、engine.py的源代码,scraper.py和scrapy/core/downloader/handlers/http11.py
似乎scrapy用来自调度程序的最多并发的\u请求填充其处理队列,并检查域,以便在以后的处理链中观察每个\u域的并发\u请求

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

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)
这是此处描述的已知问题:

替代解决方案


比将并发_请求增加到非常高的值更好的解决方案是将其用作爬行边界。。。这基本上是按照您的建议进行的:重新排序计划请求以获得最佳处理。

肯定是的,重新排序计划请求列表将有所帮助。可以这样做:

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)
不幸的是,对随后在爬网时创建的请求进行重新排序更加困难,但这可能已经有所帮助

另一个修复方法:大量增加并发请求

scrapy文档建议,如果要并行爬网多个域,则至少将并发_请求设置为100:

原因/详细解释

基于
scrapy/core/downloader.py、engine.py的源代码,scraper.py和scrapy/core/downloader/handlers/http11.py
似乎scrapy用来自调度程序的最多并发的\u请求填充其处理队列,并检查域,以便在以后的处理链中观察每个\u域的并发\u请求

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

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)
这是此处描述的已知问题:

替代解决方案


比将并发_请求增加到非常高的值更好的解决方案是将其用作爬行边界。。。这基本上就是按照你的建议:重新排列预定的请求以获得最佳处理。

好的,如果我理解:如果URL列表是A.com/1、A.com/2、A、com/3、A.com/4、B.com/1、B.com/2和concurrent_requests=3和DOWNLOAD_DELAY=1,它应该从A.com/1和B.com/1“并行”开始,然后在一秒钟后从A.com/2+B.com/2开始。这是真的吗?我不想等到A.com被爬网后再爬网B.com。是的,A.com和B.com将没有共享延迟,所以他们将一起并行。不,不会。A.com/1、A.com/2、A.com/3将填满所有3个处理插槽,因为它们将首先从调度程序中取出。另见我的答案。这是一个已知的问题:好的,如果我理解的话:如果URL列表是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。是的,A.com和B.com将没有共享延迟,所以他们将一起并行。不,不会。A.com/1、A.com/2、A.com/3将填满所有3个处理插槽,因为它们将首先从调度程序中取出。另见我的答案。这是一个众所周知的问题