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

时间:2018-11-21 08:54:05

标签: python web-scraping scrapy

我想向每个errback添加一个Request函数,以捕获DNS查找失败,超时等问题。捕获它们后,我想提交一个新项目以在管道中进行处理,以记录(在数据库中)URL x失败并出现错误y。

我可以想到两种理论方法来做到这一点(但实际上我都不知道该怎么做)。
1)以某种方式修补到搜寻器引擎中,并将新项目添加到项目处理队列中。
2)手动调用相应的管道(公平地说,我只需要调用一个),但是访问它们可能会发生类似于选项1之类的事情,以某种方式需要修补引擎,然后黑手发现管道...

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

想出了一种方法,不确定是最好还是最坏方法。

我的所有请求均收到docs中建议的errback回调。 errback是这个:

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。

答案 1 :(得分:1)

您可以创建downloader middleware并实现process_exception方法。

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