零碎的重试或重定向中间件



在用scratch浏览网站时,大约五分之一的时间我被重定向到用户阻止的页面。当这种情况发生时,我会丢失从重定向到的页面。我不知道该使用哪个中间件或在该中间件中使用什么设置,但我想要这个:

DEBUG: Redirecting (302) to (GET http://domain.com/foo.aspx) from (GET http://domain.com/bar.htm)

不要删除bar.htm。当scraper完成时,我最终没有来自bar.htm的数据,但我正在旋转代理,所以如果它再次尝试bar.htm(可能再尝试几次),我应该得到它。我如何设置尝试次数?

如果重要的话,我只允许爬网程序使用一个非常特定的起始url,然后只关注"下一页"链接,所以它应该按顺序浏览少量页面——因此我需要它重试,例如第34页,或者稍后返回。零碎的文档说默认情况下应该重试20次,但我根本看不到它在重试。如果有帮助的话:所有重定向都会转到同一个页面(一个"离开"页面,上面的foo.com)-有没有办法告诉Scrapy那个特定的页面"不算数",如果它被重定向到那里,继续重试?我在下载中间件中看到了一些引用列表中特定http代码的内容——我可以以某种方式将302添加到"始终尝试此"列表中吗?

我今天遇到了同样的问题,一个网站使用301..303重定向,但有时也使用元重定向。我已经构建了一个重试中间件,并使用了重定向中间件中的一些块:

from scrapy.contrib.downloadermiddleware.retry import RetryMiddleware
from scrapy.selector import HtmlXPathSelector
from scrapy.utils.response import get_meta_refresh
from scrapy import log
class CustomRetryMiddleware(RetryMiddleware):
def process_response(self, request, response, spider):
url = response.url
if response.status in [301, 307]:
log.msg("trying to redirect us: %s" %url, level=log.INFO)
reason = 'redirect %d' %response.status
return self._retry(request, reason, spider) or response
interval, redirect_url = get_meta_refresh(response)
# handle meta redirect
if redirect_url:
log.msg("trying to redirect us: %s" %url, level=log.INFO)
reason = 'meta'
return self._retry(request, reason, spider) or response
hxs = HtmlXPathSelector(response)
# test for captcha page
captcha = hxs.select(".//input[contains(@id, 'captchacharacters')]").extract()
if captcha:
log.msg("captcha page %s" %url, level=log.INFO)
reason = 'capcha'
return self._retry(request, reason, spider) or response
return response

为了使用这个中间件,最好在settings.py:中禁用该项目的现有重定向中间件

DOWNLOADER_MIDDLEWARES = {
'YOUR_PROJECT.scraper.middlewares.CustomRetryMiddleware': 120,
'scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware': None,
'scrapy.contrib.downloadermiddleware.redirect.MetaRefreshMiddleware': None,
}

您可以通过在spider的开头添加handle_httpstatus_list = [302]来处理302个响应,比如:

class MySpider(CrawlSpider):
handle_httpstatus_list = [302]
def parse(self, response):
if response.status == 302:
# Store response.url somewhere and go back to it later

最新更新