Scrapy 500内部服务器错误
我正在使用scrapy来抓取一个有超过400万个产品的网站。不过,在抓取了大约5万件产品后,它开始出现500的HTTP错误。我把自动限速功能关掉了,因为开启后速度很慢,抓取完成大约需要20到25天。我觉得服务器在一段时间后开始暂时阻止爬虫。有没有什么解决办法?
我正在使用网站地图爬虫——我想从网址本身提取一些信息,如果服务器没有响应,就继续下一个网址,而不是等抓取结束后关闭爬虫。为此,我在查看Request中的errback参数。不过,由于我使用的是网站地图爬虫,所以并没有明确创建Request对象。有没有什么默认的errback函数可以重写,或者我可以在哪里定义它?
还有一种方法可以做到这一点,具体可以参考这里-Scrapy: 在请求失败(例如404、500)时,如何请求另一个替代请求?
1 个回答
HTTP 500 通常表示服务器内部错误。当你被阻止时,更常见的错误是403或404。(或者可能会重定向到一个“你已被阻止”的页面)这可能是因为你访问的链接导致服务器出现问题。你应该记录下哪个请求导致了错误,然后自己尝试访问一下。也有可能是这个网站本身就有问题。
好的,我明白了,但你能告诉我在哪里以及如何定义错误回调函数,这样我就可以处理这个错误,让我的爬虫不结束吗?
我查看了SitemapSpider,不幸的是,它不允许你指定错误回调函数,所以你需要自己添加这个功能。我是根据SitemapSpider的源代码来说明的。
首先,你需要通过添加一个处理错误的函数来改变sitemap_rules
的工作方式:
sitemap_rules = [
('/product/', 'parse_product'),
('/category/', 'parse_category'),
]
将变成:
sitemap_rules = [
('/product/', 'parse_product', 'error_handler'),
('/category/', 'parse_category', 'error_handler'),
]
接下来,在init
中,你需要把新的回调函数存储在_cbs
里。
for r, c in self.sitemap_rules:
if isinstance(c, basestring):
c = getattr(self, c)
self._cbs.append((regex(r), c))
将变成:
for r, c, e in self.sitemap_rules:
if isinstance(c, basestring):
c = getattr(self, c)
if isinstance(e, basestring):
e = getattr(self, e)
self._cbs.append((regex(r), c, e))
最后,在_parse_sitemap
的末尾,你可以指定你的新错误回调函数。
elif s.type == 'urlset':
for loc in iterloc(s):
for r, c in self._cbs:
if r.search(loc):
yield Request(loc, callback=c)
break
将变成:
elif s.type == 'urlset':
for loc in iterloc(s):
for r, c, e in self._cbs:
if r.search(loc):
yield Request(loc, callback=c, errback=e)
break
从这里开始,简单地实现你的错误回调函数(记得它需要一个Twisted Failure作为参数),这样就可以了。