Выяснил способ сделать это, не уверен, что это лучший или худший способ.
Все мои запросы получают обратный вызов 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.