Scrapy 爬虫中的异常处理:如何处理 HTTP 错误和重定向?

2023-04-17 00:00:00 爬虫 重定向 如何处理

在 Scrapy 爬虫中,我们可以使用中间件(Middleware)来处理 HTTP 错误和重定向。中间件是一种可以在请求和响应之间进行处理的组件。Scrapy 提供了一些内置的中间件来帮助我们处理 HTTP 错误和重定向。

首先,我们需要开启 Scrapy 的异常处理和重定向功能。在 settings.py 文件中添加以下配置:

HTTPERROR_ALLOWED_CODES = [404, 403]  # 允许处理的 HTTP 错误码
REDIRECT_ENABLED = True  # 开启重定向功能

然后,我们可以编写一个中间件来处理 HTTP 错误和重定向:

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

class HttpErrorAndRedirectMiddleware:
    @classmethod
    def from_crawler(cls, crawler):
        middleware = cls()

        crawler.signals.connect(
            middleware.spider_error, signal=signals.spider_error)

        return middleware

    def spider_error(self, failure, response, spider):
        if response is not None:
            # 处理 HTTP 错误
            if response.status in self.settings.getlist('HTTPERROR_ALLOWED_CODES'):
                spider.logger.info('[Error] Ignoring response %s, code=%d', response.url, response.status)
                return None
            # 处理重定向
            if response.status in [301, 302, 303, 307]:
                redirected_url = response.headers.get('Location').decode('utf-8')
                spider.logger.info('[Redirect] Redirecting %s to %s', response.url, redirected_url)
                new_request = response.request.replace(url=redirected_url)
                return new_request
        else:
            raise IgnoreRequest('[Error] Failure %s' % failure)

    def process_exception(self, request, exception, spider):
        if isinstance(exception, IgnoreRequest):
            spider.logger.info('[Error] Ignoring request %s', request.url)
            return None
        return request

在上面的代码中,我们定义了一个类 HttpErrorAndRedirectMiddleware,它实现了 Scrapy 的中间件接口。其中:

  • from_crawler() 方法是 Scrapy 的钩子方法,用于获得 Scrapy 的设置和信号。在这个方法中,我们注册了一个 spider_error 信号,它会在爬虫遇到错误时被触发。
  • spider_error() 方法接收一个 failure 对象、一个响应对象和一个 Spider 对象。其中,failure 对象是一个 Twisted 的 Failure 对象,它表示了错误的信息;响应对象是响应的信息;Spider 对象是爬虫对象。
  • 如果响应对象不是 None,并且响应的状态码在允许处理的 HTTP 错误码范围内,那么我们就将其忽略;
  • 如果响应对象不是 None,并且响应的状态码是重定向状态(301、302、303、307),那么我们就获取重定向的目标 URL,并创建一个新的请求对象,将其发送到新的 URL;
  • 如果响应对象是 None,那么我们就抛出一个 IgnoreRequest 的异常,表示这个请求被忽略。
  • process_exception() 方法是 Scrapy 的中间件接口方法,用于处理异常。在这个方法中,我们判断异常是否是 IgnoreRequest,如果是,那么我们就忽略这个请求,否则我们就将异常传递给下一个中间件。

最后,我们在 settings.py 文件中设置中间件:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.HttpErrorAndRedirectMiddleware': 100,
}

这样,我们就成功地处理了 Scrapy 爬虫中的 HTTP 错误和重定向。下面是一个简单的演示:

import scrapy

class PidancodeSpider(scrapy.Spider):
    name = 'pidancode'
    allowed_domains = ['pidancode.com']
    start_urls = ['http://www.pidancode.com/']

    def parse(self, response):
        raise scrapy.exceptions.CloseSpider('Test close spider with error')

在这个演示中,我们将爬虫的起始 URL 设置为 pidancode.com,然后在 parse() 方法中抛出了一个异常。如果我们没有创建上面的中间件来处理异常,那么这个异常会导致整个爬虫停止,我们将无法获得任何数据。但如果使用了我们创建的中间件,这个异常会被忽略,爬虫会继续运行。

以上就是 Scrapy 爬虫中处理 HTTP 错误和重定向的详细讲解,以及相应的代码演示。

相关文章