如何在scrapy中捕获并处理各种异常

  • Post category:Python

在Scrapy中,异常处理是非常重要的一部分,它可以确保我们的爬虫程序在遇到意外错误时不会崩溃并停止工作。一些常见的异常包括:超时异常、下载异常、解析异常等等。在这里,我们将提供一份攻略,介绍如何在Scrapy中捕获并处理各种异常。

1. 下载中间件

Scrapy的下载中间件Middleware提供了处理异常的机制。可以通过编写自定义的中间件来捕获并处理异常。其中,建议在下载中间件中添加处理异常的代码,因为在下载过程中抛出的异常,大多数都是由于传输或连接错误(如超时和网络错误)导致的。以下是一个自定义下载中间件捕获所有下载异常的示例:

from scrapy import signals
from scrapy.exceptions import NotConfigured, IgnoreRequest

class DownloadErrorMiddleware(object):

    @classmethod
    def from_crawler(cls, crawler):
        if not crawler.settings.getbool('MYEXT_ENABLED'):
            raise NotConfigured

        ext = cls()

        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)

        return ext

    def process_request(self, request, spider):
        return None

    def process_response(self, request, response, spider):
        if response.status_code == 404:  # 捕获HTTP错误
            raise IgnoreRequest("Not Found: {}".format(response.url))
        if response.status_code == 500:  # 捕获HTTP错误
            raise IgnoreRequest("Internal Server Error: {}".format(response.url))
        return response

    def process_exception(self, request, exception, spider):
        if isinstance(exception, ConnectionRefusedError)  # 捕获连接错误
            raise IgnoreRequest("Connection Refused: {}".format(request.url))
        if isinstance(exception, TimeoutError):  # 捕获超时错误
            raise IgnoreRequest("Timeout: {}".format(request.url))
        if isinstance(exception, DownloadError):  # 捕获下载错误
            raise IgnoreRequest("Download Error: {}".format(request.url))
        return None

    def spider_closed(self, spider):
        pass

2. 重试下载策略

另一种常见的方法是使用Scrapy内置的下载重试中间件RetryMiddleware。它可以重试下载多次,直到达到最大重试次数(由重试中间件设置的值)。 但值得注意的是,在通过配置RetryMiddleware时,如果设置了过低的重试次数(比如1或2),可能会导致爬虫在遇到可恢复的异常情况(如网络延迟)时过早地中止。

以下是一个关于如何配置RetryMiddleware的示例:

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.retry.RetryMiddleware': True,
}

RETRY_ENABLED = True  # 是否开启重试
RETRY_TIMES = 5  # 重试次数
RETRY_HTTP_CODES = [500, 502, 503, 504, 400, 408]  # 重试的HTTP状态码

其中,RETRY_HTTP_CODES是最值得关注的选项之一。它的值应设置为需要重试的HTTP状态码列表。 Scrapy默认只在遇到HTTP状态码为500、502、503、504时进行重试。如果网站返回的实际状态码与RETRY_HTTP_CODES设置不同,则不会重试。

综上所述,在Scrapy中我们可以通过编写自定义下载中间件来捕获并处理各种异常,在下载重试中间件RetryMiddleware的帮助下实现重试下载,这样可以更好地为我们的爬虫程序提供异常处理机制,从而在爬取数据时实现更为健壮的程序。