如何在scrapy.Request中添加dont_filter = True参数使我的解析方法起作用?
下面是一个简单scrapy蜘蛛如何在scrapy.Request中添加dont_filter = True参数使我的解析方法起作用?
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 =真在请求方法的参数,使parse2功能工作。
yield scrapy.Request(self.start_urls[0],callback=self.parse2,dont_filter=True)
但在scrapy文档和很多在YouTube上的教程中给出的例子,他们从来没有使用过dont_filter = True参数在scrapy.Request方法仍然是他们的第二解析功能的工作原理。
看看这个
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 =真被添加?我究竟做错了什么 ?我的蜘蛛在第一个例子中过滤的重复链接是什么?
P.S.我可以在我上面发布的QA线程中解决这个问题,但是我不允许发表评论,除非我有50个声望(可怜我!!)
简短回答:您正在进行重复请求。 Scrapy内置了默认打开的重复筛选。这就是为什么parse2
没有被调用。当您添加dont_filter=True
时,scrapy不会过滤出重复的请求。所以这次请求被处理。
较长版本:
在Scrapy,如果已经设置start_urls
或具有方法start_requests()
定义,蜘蛛自动请求这些网址并传递给parse
方法,该方法是用于解析的默认方法的响应要求。现在你可以从这里产生新的请求,这将再次被Scrapy解析。如果您未设置回拨,parse
方法将再次使用。如果您设置回调,则会使用该回调。
Scrapy还具有内置的过滤器,可以阻止重复的请求。这就是说,如果Scrapy已经抓取一个网站并解析了响应,即使您通过该网址发出另一个请求,scrapy也不会处理它。
就你而言,你的网址为start_urls
。 Scrapy从该网址开始。它抓取该网站并将响应传递给parse
。在parse
方法的内部,您再次向相同的网址(刚刚处理的scrapy)发出请求,但这次是parse2
作为回调。当这个请求被取消时,scrapy认为这是重复的。所以它忽略了请求并且从不处理它。所以没有拨打电话parse2
。
如果要控制哪些URL应该被处理且回调使用,我建议你重写start_requests()
并返回,而不是使用单start_urls
属性scrapy.Request
列表。
我想你的意思是重写'start_requests', get_start_urls'不是你最后一段中的东西。 – Granitosaurus
我的不好,是的,我正在更新答案。我从记忆中写下,忘了名字。 – masnun
我从未想过'start_urls'中的网址会被自动解析。非常感谢您的帮助和时间 –
你有两次下载同一页面的原因吗?Scrapy会过滤您的请求,因此您不会最终抓取相同的页面,'dont_filter'完全意味着忽略此过滤器。 – Granitosaurus
与你的问题没有关系,但可能很快就会咬你:'allowed_domains'应该列出域名,而不是URL,所以它应该是'allowed_domains = [“dmoz.org”]' –