【问题标题】:Scrapy rules not working when process_request and callback parameter are set设置 process_request 和回调参数时,Scrapy 规则不起作用
【发布时间】:2016-11-11 19:38:06
【问题描述】:

我对scrapy有这个规则CrawlSpider

rules = [
        Rule(LinkExtractor(
                    allow= '/topic/\d+/organize$', 
                    restrict_xpaths = '//div[@id= "zh-topic-organize-child-editor"]'
                    ),
           process_request='request_tagPage', callback = "parse_tagPage", follow = True)
    ]

request_tagePage() 指的是在请求中添加 cookie 的函数,parse_tagPage() 指的是解析目标页面的函数。根据documentation,CrawlSpider 应该使用request_tagPage 发出请求,一旦返回响应,它就会调用parse_tagPage() 来解析它。但是,我意识到当使用request_tagPage() 时,蜘蛛根本不会调用parse_tagPage()。所以在实际代码中,我在request_tagPage中手动添加了parse_tagPage()回调函数作为回调,像这样:

def request_tagPage(self, request):
    return Request(request.url, meta = {"cookiejar": 1}, \ # attach cookie to the request otherwise I can't login
            headers = self.headers,\
            callback=self.parse_tagPage) # manually add a callback function.

它工作了,但现在蜘蛛不使用规则来扩展它的爬行。它在抓取来自start_urls 的链接后关闭。但是,在我手动将parse_tagPage() 设置为request_tagPage() 的回调之前,规则有效。所以我在想这可能是一个错误?有一种方法可以启用request_tagPage(),我需要在请求中附加cookie,parse_tagPage(),用于解析页面和rules,指导蜘蛛爬行?

【问题讨论】:

  • 您确定您的链接提取器是否正常工作?通过scrapy shell url 打开一个网站并导入 LinkExtractor 并尝试在response.body 上使用相同的参数。
  • 它工作正常。当 parse_tagPage() 不用作 request_tagPage() 中的回调函数时,我从控制台看到蜘蛛应该按原样爬行。从scrapy的documentation on Rule object,我认为将 parse_tagPage() 设置为 Rule 的回调就足够了,结果根本没有调用回调函数。所以我必须把回调放在request_tagPage() 中。然后回调被调用,但蜘蛛失去了跟踪链接的能力,除了 start_urls 中的链接。
  • 您是否尝试过不构造全新的Request 对象,而是使用Request.replace() 方法?例如。 return request.replace(meta={'cookiejar': 1}, headers=self.headers)CrawlSpider 在其自己的处理爬网规则的 parse() 回调中处理所有页面,因此手动更改 callback 似乎不是一个好方法。
  • @shirk3y 尝试使用 request.replace()。然而,它的工作原理相同。同样感谢

标签: callback scrapy web-crawler rules


【解决方案1】:

CrawlSpider 规则生成的请求使用internal callbacks and use meta to do their "magic"

我建议您不要在规则的 process_request 挂钩中重新创建请求(否则您可能最终会重新实现 CrawlSpider 已经为您所做的事情)。

相反,如果您只想添加 cookie 和特殊标头,则可以使用传递给 request_tagPage.replace() method on the request,从而保留 CrawlSpider 的“魔力”。

这样的事情就足够了:

def request_tagPage(self, request):
    tagged = request.replace(headers=self.headers)
    tagged.meta.update(cookiejar=1)
    return tagged

【讨论】:

    【解决方案2】:

    我发现了问题。 CrawlSpider 使用其默认的 parse() 来应用规则。所以当我的自定义parse_tagPage() 被调用时,没有更多的parse() 跟进来继续应用规则。解决方案是简单地将默认的parse() 添加到我的自定义parse_tagPage() 中。现在看起来像这样:

    def parse_tagPage(self, response):
        # parse the response, get the information I want...
        # save the information into a local file...
        return self.parse(response) # simply calls the default parse() function to enable the rules
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      相关资源
      最近更新 更多