Scrapy框架是一个爬虫框架,通过异步、并发的方式高效地运行爬虫程序。在爬取网站过程中,可能会遇到不同类型的异常,例如网络连接中断、http状态码错误和解析异常等,这些异常如果不及时处理,会导致爬虫程序中断或者无法正常工作。因此,Scrapy框架提供了一系列的异常处理方式,帮助用户处理各种异常。
捕获并处理异常
在Scrapy框架中,捕获和处理异常主要有如下几种方式:
1. 异常处理中间件
Scrapy框架提供了一个通用的中间件机制,通过继承scrapy.middleware.BaseMiddleware
类并实现相应的方法,可以在整个请求响应流程中拦截并处理异常。具体实现步骤如下:
- 创建一个异常处理类,继承
scrapy.middleware.BaseMiddleware
类,并实现相应的方法,例如process_request()
、process_response()
和process_exception()
方法。 -
在settings.py文件中启用自定义中间件,参考代码如下:
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.MyMiddleware': 543,
} -
在
process_exception()
方法中实现自定义异常处理逻辑。例如,处理网络异常的代码示例:```python
import logging
from scrapy import signalsclass NetworkError(Exception):
passclass MyMiddleware(object):
def process_exception(self, request, exception, spider): if isinstance(exception, NetworkError): # 进一步处理网络异常 logging.error('Network Error: %s' % exception) else: return None
```
2. Request或Response处理函数
在Scrapy框架中,每个Request和Response对象都有处理函数,分别为errback
和callback
。其中callback
函数用于处理请求成功后返回的响应,errback
函数用于处理请求失败或者返回错误码的响应。通过重载errback
函数,可以实现自定义的异常处理逻辑。例如,处理404错误的代码示例:
def parse(self, response):
if response.status == 404:
self.logger.info('Page not found: %s' % response.url)
else:
# parse logic
pass
def on_error(self, failure):
if failure.check(HttpError):
response = failure.value.response
if response.status == 404:
self.logger.info('Page not found: %s' % response.url)
elif failure.check(TimeoutError, DNSLookupError, TCPTimedOutError):
# 处理网络错误
pass
else:
self.logger.error('Unhandled exception: %s' % failure.value)
3. Callback中的try-except语句
在Scrapy爬虫程序中,我们可以在回调函数中使用try-except
语句捕获并处理异常。例如,捕获解析异常的代码示例:
def parse_detail(self, response):
try:
content = response.xpath('//div[@class="content"]/text()').extract()
# 处理解析结果
except Exception as e:
logging.error('Content parse failed: %s' % e)
示例说明
下面通过两个示例详细讲解如何在Scrapy中捕获和处理各种异常。
示例1:捕获网络异常
假设我们要爬取一个网站,并且网站可能会出现网络异常,例如DNS解析失败、连接超时等。此时,我们可以通过自定义中间件的方式,捕获并处理网络异常。
代码示例:
import logging
import requests
from scrapy import signals
from scrapy.exceptions import IgnoreRequest
class NetworkExceptionMiddleware(object):
def process_exception(self, request, exception, spider):
if isinstance(exception, requests.exceptions.RequestException):
logging.error('Network Error: %s, url=%s' % (exception, request.url))
raise IgnoreRequest
在上述代码中,我们自定义了一个名为NetworkExceptionMiddleware
中间件类,实现了process_exception
方法,在该方法中判断异常类型是否是requests库中的异常,如果是则输出异常信息,并通过raise语句抛出IgnoreRequest异常。此时,Scrapy框架会自动跳过出现异常的请求,并打印日志信息。在settings.py中配置该中间件:
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.NetworkExceptionMiddleware': 543,
}
示例2:处理响应解析异常
假设我们要爬取一个网站,需要通过XPath解析获取网页内容,并对解析结果进行处理。在XPath解析过程中,有可能会出现语法错误或者其他解析异常。此时,我们可以在回调函数中使用try-except
语句,捕获并处理异常。
代码示例:
def parse_detail(self, response):
try:
content = response.xpath('//div[@class="content"]/text()').extract()
# 处理解析结果
except Exception as e:
logging.error('Content parse failed: %s, url=%s' % (e, response.url))
在上述代码中,我们使用try-except
语句捕获解析异常,并通过logging
模块输出日志信息,指出解析出错的原因和响应页面的URL。同时也可以添加其他处理逻辑,比如重新发起请求等操作。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何在scrapy中捕获并处理各种异常 - Python技术站