代码之家  ›  专栏  ›  技术社区  ›  wanaryytel

在请求错误回调中处理新项

  •  1
  • wanaryytel  · 技术社区  · 7 年前

    我想添加一个 errback 对每个 Request 以捕获DNS查找失败、超时等。在捕获它们之后,我想提交一个新的项目,在管道中进行处理,以记录(在数据库中)URL X因错误Y而失败。

    我可以想出两种理论上的方法(但实际上我也不知道该怎么做)。
    1)以某种方式修补爬虫引擎,并将新项目添加到项目处理队列。
    2)手动调用各自的管道(我只需要调用一个管道来保持公平),但访问它们可能与选项1类似,不知何故需要修补引擎,然后黑客发现管道…

    有什么建议吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Guillaume    7 年前

    你可以创造你的 downloader middleware 并实施 process_exception 方法。

    您可以访问请求对象,因此可以将详细信息写入数据库,然后返回新的请求。

        2
  •  0
  •   wanaryytel    7 年前

    算出 这样做的方式,不确定这是最好还是最坏的方式。

    我的所有请求都会收到 errback 按中的建议回调 docs .这个 错位 是这样的:

    def process_failed_request(self, failure):
        status = 'Unknown problem'
    
        if failure.check(HttpError) or failure.check(IgnoreRequest):
            return
        elif failure.check(twisted_errors.DNSLookupError):
            status = 'Server not found'
        elif failure.check(TimeoutError, twisted_errors.TCPTimedOutError):
            status = '408'
        elif failure.check(twisted_errors.SSLError):
            status = 'SSL error'
        elif failure.check(twisted_errors.ConnectError):
            status = 'Connection error'
    
        item = {
            'visited_page': LightRequest(None, url=failure.request.url, status_code=status),
        }
    
        # Force scrapy to process the failed item as it was a normal item
        self.crawler.engine.scraper.slot.itemproc_size += 1
        dfd = self.crawler.engine.scraper.itemproc.process_item(item, self)
        dfd.addBoth(self.crawler.engine.scraper._itemproc_finished, item, None, self)
    

    不要在意上半部分发生了什么,但三条底线就是魔力。第一行增加项目处理队列计数器以限制 CONCURRENT_ITEMS 正确地。第二行调用处理,第三行添加Scrapy为每个处理的项目添加的回调。这个 None 论证是 response 这个值实际上也可以放入,至少对于某些错误是这样的。您可以从 failure.value.response 但我现在不在乎。

    哦,如果不清楚,那么 self Spider 当然。

    PS!因为这很大程度上依赖于Scrapy引擎,所以我使用的版本是1.5.1。