2015-09-19 95 views
2

对于我试图抓取的页面,我有时会在我的响应中返回一个“占位符”页面,其中包含一些JavaScript,它会自动重新加载,直到它获得真实页面。我可以检测到这种情况,并且我想重新尝试下载和抓取页面。我在我的CrawlSpider使用的逻辑是这样的:Scrapy CrawlSpider重试刮

def parse_page(self, response): 
    url = response.url 

    # Check to make sure the page is loaded 
    if 'var PageIsLoaded = false;' in response.body: 
     self.logger.warning('parse_page encountered an incomplete rendering of {}'.format(url)) 
     yield Request(url, self.parse, dont_filter=True) 
     return 

    ... 
    # Normal parsing logic 

然而,这似乎是在重试逻辑被称为一个新的请求发出后,页面和它们含有不抓取的链接或刮掉。我的想法是,通过使用CrawlSpider使用的self.parse来应用爬网规则和dont_filter=True,我可以避免重复的过滤器。但与DUPEFILTER_DEBUG = True,我可以看到重试请求被过滤掉。

我错过了什么,还是有更好的方法来处理这个问题?如果可能的话,我想避免使用类似飞溅的动态js渲染的复杂性,而且这只会间歇性地发生。

回答

5

我会考虑改为使用custom Retry Middleware--类似于built-in one

样品执行(未测试):

import logging 

logger = logging.getLogger(__name__) 


class RetryMiddleware(object): 
    def process_response(self, request, response, spider): 
     if 'var PageIsLoaded = false;' in response.body: 
      logger.warning('parse_page encountered an incomplete rendering of {}'.format(response.url)) 
      return self._retry(request) or response 

     return response 

    def _retry(self, request): 
     logger.debug("Retrying %(request)s", {'request': request}) 

     retryreq = request.copy() 
     retryreq.dont_filter = True 
     return retryreq 

而且不要忘了activate它。

+0

中间件工作得很漂亮。我几乎可以重新使用内置的重试中间件,只是去掉异常代码,并用我自己的测试代替它。再次感谢你的帮助。 – JoshAdel

+0

@JoshAdel是的,scrapy确实使一切都变得模块化和干净 - 所有的管道,中间件,扩展,项目加载器,输入和输出处理器都是非常重要的API接口,通常是非常棘手的网页抓取领域。很高兴帮助和感谢一个有趣的问题! – alecxe