Scrapy架构图
网上最多的一张scrapy架构图:
可以看到所有的数据流都是要经过Scrapy Engine的,这是一个中转站。它没有给出顺序,只能分析有哪些组件,所以我们看下图。
scrapy官方文档提供的架构图:
其实自己理解理解这张图就能大致明白scrapy的一些原理了。主要不要忽略了两处的middleware,45过程经过的是download middleware,而67过程经过的是spider middleware。
为了进一步理解,我们可以读一读scrapy的源码,我们刚刚看到的各个组件,除了spider和pipeline是由我们自己编写,实际上都在scrapy包下的core包中可以找到:
上面的1过程就是我们的spider中写的yield。
2过程通过engine.py中的下面的方法解决:
def schedule(self, request, spider):
self.signals.send_catch_log(signal=signals.request_scheduled,
request=request, spider=spider)
if not self.slot.scheduler.enqueue_request(request):
self.signals.send_catch_log(signal=signals.request_dropped,
request=request, spider=spider)
3过程通过engine.py中的下面的方法解决:
def _next_request_from_scheduler(self, spider):
slot = self.slot
request = slot.scheduler.next_request()
if not request:
return
d = self._download(request, spider)
d.addBoth(self._handle_downloader_output, request, spider)
d.addErrback(lambda f: logger.info('Error while handling downloader output',
exc_info=failure_to_exc_info(f),
extra={'spider': spider}))
d.addBoth(lambda _: slot.remove_request(request))
d.addErrback(lambda f: logger.info('Error while removing request from slot',
exc_info=failure_to_exc_info(f),
extra={'spider': spider}))
d.addBoth(lambda _: slot.nextcall.schedule())
d.addErrback(lambda f: logger.info('Error while scheduling new request',
exc_info=failure_to_exc_info(f),
extra={'spider': spider}))
return d
下图说明我们的downloader是支持很多种下载的:
接下来你可以看看scrapy源码的组织结构,它与django是很像的,同时也可以自己调试看看程序的执行过程。