目录

  • 下载中间件(Download MiddleWare)是如何加载的
  • Spider MiddleWare是如何加载的
  • 配置文件是如何起作用的
  • 整体的执行流程是怎样的
  • 扩展件是如何工作的
  • 数据是怎么处理的

分析

 

我们正常的思路就是从spider的parse方法来着手,因为我们写的最多的代码就是从这里开始的,这样我们直接从scraper.py来看

def call_spider(self, result, request, spider):
        result.request = request
        dfd = defer_result(result)
        dfd.addCallbacks(request.callback or spider.parse, request.errback)
        return dfd.addCallback(iterate_spider_output)

 

这里我就们就可以看到spider如果指定了callback,那callback对应的方法优先级最高,如果没有callback,那就是默认的spider.parse方法,我们来看看谁在调用这个call_spider方法

到最后一步的时候其实已经跨到engine.py了,我们不是经常写yield Request或者yield item这种方法吗?这yield和return 有什么区别呢,不急,我们先看看是怎么处理我们的输出的,先看如下的代码:

def _process_spidermw_output(self, output, request, response, spider):
        """Process each Request/Item (given in the output parameter) returned
        from the given spider
        """
        if isinstance(output, Request):
            self.crawler.engine.crawl(request=output, spider=spider)
        elif isinstance(output, (BaseItem, dict)):
            self.slot.itemproc_size += 1
            dfd = self.itemproc.process_item(output, spider)
            dfd.addBoth(self._itemproc_finished, output, response, spider)
            return dfd
        elif output is None:
            pass
        else:
            typename = type(output).__name__
            logger.error('Spider must return Request, BaseItem, dict or None, '
                         'got %(typename)r in %(request)s',
                         {'request': request, 'typename': typename},
                         extra={'spider': spider})

 

拿到返回的内容之后,先判断是item 还是request,如果是item ,则调用process_item方法-就是我们在pipeline里面的定义的内容,这里被加载进来之后做数据的方法,如果是request类型呢,就放回到队列之中,然后进一步的处理。

我们小小看一步是如何处理的

看看这个_scrape_next方法

def _scrape_next(self, spider, slot):
        while slot.queue:
            response, request, deferred = slot.next_response_request_deferred()
            self._scrape(response, request, spider).chainDeferred(deferred)

信号槽中一直存在队列的时候,那就一直处理直到结束,一直调用_scrape方法。这样整个的流程和逻辑就清晰了.