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