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

时间:2016-08-15 08:39:00

标签: web-scraping scrapy scrapy-spider

这是一个简单的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个声望(可怜的我!!)

1 个答案:

答案 0 :(得分:6)

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

更长的版本:

在Scrapy中,如果您已设置start_urls或已定义方法start_requests(),则蜘蛛会自动请求这些网址并将响应传递给parse方法,这是使用的默认方法用于解析请求。现在,您可以从此处生成新请求,这些请求将再次由Scrapy解析。如果您未设置回调,则会再次使用parse方法。如果设置回调,则将使用该回调。

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

在您的情况下,您有start_urls中的网址。 Scrapy从那个url开始。它会抓取网站并将响应传递给parse。在parse方法中,您再次向同一个网址发出请求(scrapy刚刚处理完)但这次使用parse2作为回调。当这个请求产生时,scrapy认为这是一个副本。因此它忽略了请求并且从不处理它。因此,不会调用parse2

如果您想控制应该处理哪些网址以及要使用哪个回调,我建议您覆盖start_requests()并返回scrapy.Request的列表,而不是使用单个start_urls属性。