【问题标题】:Scrapy retry or redirect middlewareScrapy 重试或重定向中间件
【发布时间】:2013-12-27 18:33:48
【问题描述】:

在使用 scrapy 爬取网站时,大约 1/5 的时间我会被重定向到用户屏蔽的页面。发生这种情况时,我会丢失从 重定向的页面。我不知道要使用哪个中间件或在该中间件中使用什么设置,但我想要这个:

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

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

如果重要的话,我只允许爬虫使用一个非常具体的起始网址,然后只跟随“下一页”链接,所以它应该按顺序通过少数页面 - 因此我需要它要么重试,例如第 34 页,要么稍后再返回。 Scrapy 文档说默认情况下它应该重试 20 次,但我根本没有看到它重试。此外,如果它有帮助:所有重定向都转到同一页面(“离开”页面,上面的 foo.com) - 有没有办法告诉 Scrapy 该特定页面“不计算在内”以及它是否被重定向到那里,继续重试?我在下载器中间件中看到了一些引用列表中特定 http 代码的内容 - 我可以以某种方式将 302 添加到“始终尝试这个”列表中吗?

【问题讨论】:

    标签: python redirect python-2.7 scrapy


    【解决方案1】:

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

    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,
    }
    

    【讨论】:

      【解决方案2】:

      您可以通过在蜘蛛的开头添加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
      

      【讨论】:

      • 只是想添加一个更广泛的解决方案(不一定适用于这个问题)重定向也使用HTTP状态代码307(注意日志),所以在这种情况下你可以替换@ 987654323@ 和 handle_httpstatus_list = [302, 307]if response.status == 302:if response.status in self.handle_httpstatus_list:
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多