【发布时间】:2019-11-13 15:42:00
【问题描述】:
使用 Scrapy,我正在实现一个 CrawlSpider,它将抓取各种网站,因此,有时非常慢的网站最终会产生超时。
我的问题是,如果发生这样的twisted.internet.error.TimeoutError,我想触发我的蜘蛛的 errback。我不想引发这个异常,我也不想返回一个可能表明抓取成功的虚拟响应对象。
请注意,我已经能够完成所有这些工作,但只能使用“肮脏”的解决方法:
myspider.py(摘录)
class MySpider(CrawlSpider):
name = 'my-spider'
rules = (
Rule(
link_extractor=LinkExtractor(unique=True),
callback='_my_callback', follow=True
),
)
def parse_start_url(self, response):
# (...)
def errback(self, failure):
log.warning('Failed scraping following link: {}'
.format(failure.request.url))
middlewares.py(摘录)
from twisted.internet.error import DNSLookupError, TimeoutError
# (...)
class MyDownloaderMiddleware(object):
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_request(self, request, spider):
return None
def process_response(self, request, response, spider):
return response
def process_exception(self, request, exception, spider):
if (isinstance(exception, TimeoutError)
or (isinstance(exception, DNSLookupError))):
# just 2 examples of errors i want to catch
# set status=500 to enforce errback() call
return Response(request.url, status=500)
我的自定义中间件已经启用,设置应该没问题。
现在您可以通过使用return Response(request.url, status=500) 看到,我可以根据需要在 MySpider 中触发我的errback() 函数。但是,状态代码 500 非常具有误导性,因为它不仅不正确,而且从技术上讲,我根本没有收到任何响应。
所以我的问题是,我怎样才能以干净的方式通过DownloaderMiddleware.process_exception() 触发我的errback() 函数?
编辑:我很快发现对于类似的异常,如DNSLookupError,我希望有相同的行为。我已经相应地更新了编码 sn-ps。
【问题讨论】: