在 scrapy.Request 中添加 dont_filter=True 参数如何使我的解析方法起作用?

How does adding dont_filter=True argument in scrapy.Request make my parsing method to work ?

这是一个简单的 scrapy 蜘蛛

import scrapy

class ExampleSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["https://www.dmoz.org"]
    start_urls = ('https://www.dmoz.org/')

    def parse(self,response):
        yield scrapy.Request(self.start_urls[0],callback=self.parse2)

    def parse2(self, response):
        print(response.url)

当您 运行 程序时,parse2 方法不起作用并且不打印 response.url。然后我在下面的线程中找到了解决方案。

Why is my second request not getting called in the parse method of my scrapy spider

只是我需要在请求方法中添加 dont_filter=True 作为参数以使 parse2 函数工作。

yield scrapy.Request(self.start_urls[0],callback=self.parse2,dont_filter=True)

但是在 scrapy 文档和许多 youtube 教程中给出的示例中,他们从未在 scrapy.Request 方法中使用 dont_filter = True 参数,并且他们的第二个解析函数仍然有效。

看看这个

def parse_page1(self, response):
    return scrapy.Request("http://www.example.com/some_page.html",
                      callback=self.parse_page2)

def parse_page2(self, response):
    # this would log http://www.example.com/some_page.html
    self.logger.info("Visited %s", response.url)

除非添加 dont_filter=True,否则为什么我的蜘蛛无法工作?我究竟做错了什么 ?我的蜘蛛在我的第一个例子中过滤掉了哪些重复链接?

P.S。我本可以在我上面发布的 QA 线程中解决这个问题,但除非我有 50 个声誉,否则我不能发表评论(可怜的我!!)

简答:您正在重复请求。 Scrapy 内置了默认开启的重复过滤功能。这就是 parse2 没有被调用的原因。当您添加 dont_filter=True 时,scrapy 不会过滤掉重复的请求。所以这次请求被处理了。

更长的版本:

在 Scrapy 中,如果你设置了 start_urls 或定义了方法 start_requests(),蜘蛛会自动请求那些 url 并将响应传递给 parse方法,这是用于解析请求的默认方法。现在你可以从这里产生新的请求,这些请求将再次被 Scrapy 解析。如果不设置回调,会再次使用parse方法。如果您设置回调,将使用该回调。

Scrapy 还有一个内置的过滤器可以阻止重复的请求。也就是说,如果 Scrapy 已经抓取了一个站点并解析了响应,即使你用 url 产生另一个请求,scrapy 也不会处理它。

在您的例子中,您在 start_urls 中有 url。 Scrapy 以 url 开头。它抓取网站并将响应传递给 parse。在 parse 方法中,您再次向同一个 url (scrapy 刚刚处理过)发出请求,但这次使用 parse2 作为回调。当此请求被产生时,scrapy 将其视为重复项。所以它忽略请求并且从不处理它。所以没有调用 parse2

如果你想控制应该处理哪些urls和使用哪个回调,我建议你覆盖start_requests()和return列表scrapy.Request 而不是使用单个 start_urls 属性。