如何处理scrapy项目中的各种异常,在errback和回调中?

Sha*_*Lau 10 python scrapy

我目前正在开发一个刮刀项目,这对于确保每个请求得到妥善处理非常重要,即记录错误或保存成功结果.我已经实现了基本的蜘蛛,我现在可以成功处理99%的请求,但是我可能会遇到像captcha,50x,30x,甚至结果中没有足够字段的错误(然后我会尝试另一个网站到找到缺少的字段).

起初,我认为在解析回调中引发异常并在errback中处理所有异常更"合乎逻辑",这可以使代码更具可读性.但我试图发现errback只能捕获下载器模块中的错误,例如非200响应状态.如果我在回调中引发一个自我实现的ParseError,那么蜘蛛只会提升它并停止.

即使我必须直接在回调中处理解析请求,我也不知道如何在回调中立即以干净的方式重试请求.你知道,我可能必须包含一个不同的代理来发送另一个请求,或修改一些请求标头.

我承认我对scrapy相对较新,但我已经来回试了好几天但仍然无法让它工作......我已经检查过每一个问题而没有人匹配,提前感谢你的帮助.

更新:我意识到这可能是一个非常复杂的问题所以我试着在下面的伪代码中说明这个场景,希望这会有所帮助:

from scraper.myexceptions import *

def parseRound1(self, response):

    .... some parsing routines ...
    if something wrong happened:
       # this causes the spider raises a SpiderException and stops
       raise CaptchaError
    ...

    if no enough fields scraped:
       raise ParseError(task, "no enough fields")
    else:
       return items

def parseRound2(self, response):
    ...some other parsing routines...

def errHandler(self, failure):
    # how to trap all the exceptions?
    r = failure.trap()
    # cannot trap ParseError here
    if r == CaptchaError:
       # how to enqueue the original request here?
       retry
    elif r == ParseError:
        if raised from parseRound1:
            new request for Round2
        else:
            some other retry mechanism
    elif r == HTTPError:
       ignore or retry
Run Code Online (Sandbox Code Playgroud)

Sja*_*aak 9

编辑2012年11月16日:Scrapy> = 0.16使用不同的方法将方法附加到信号,添加了额外的示例

最简单的解决方案是使用Scrapy信号编写一个可以捕获故障的扩展.例如; 以下扩展将捕获所有错误并打印回溯.

您可以对失败做任何事情 - 比如保存到您的数据库,或发送一封电子邮件 - 它本身就是twisted.python.failure.Failure的一个实例.

对于Scrapy版本,直到0.16:

from scrapy import signals
from scrapy.xlib.pydispatch import dispatcher

class FailLogger(object):
  def __init__(self):
    """ 
    Attach appropriate handlers to the signals
    """
    dispatcher.connect(self.spider_error, signal=signals.spider_error)

  def spider_error(self, failure, response, spider):
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback())
Run Code Online (Sandbox Code Playgroud)

对于0.16及以上的Scrapy版本:

from scrapy import signals

class FailLogger(object):

  @classmethod
  def from_crawler(cls, crawler):
    ext = cls()

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

    return ext

  def spider_error(self, failure, response, spider):
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback())  
Run Code Online (Sandbox Code Playgroud)

您可以在设置中启用扩展程序,例如:

EXTENSIONS = {
'spiders.extensions.faillog.FailLogger': 599,
}
Run Code Online (Sandbox Code Playgroud)


war*_*iuc 3

起初,我认为在解析回调中引发异常并在 errback 中处理它们更“合乎逻辑”,这可以使代码更具可读性。但我尝试发现 errback 只能捕获下载器模块中的错误,例如非 200 响应状态。如果我在回调中引发一个自行实现的 ParseError,蜘蛛就会引发它并停止。

是的,你是对的 -callback并且errback只能与下载器一起使用,就像twisted用于下载资源一样,并且扭曲使用延迟 - 这就是需要回调的原因。

scrapy 中唯一的异步部分通常是下载器,所有其他部分都是同步工作的。

因此,如果您想捕获所有非下载器错误 - 自己动手:

  • 在回调中进行一次大尝试/例外
  • 或者为你的回调创建一个装饰器来执行此操作(我更喜欢这个想法)