scrapy 架构源码分析
- 1、Spiders ->网页分析器
- 2、Item Pipline -> 数据管道
- 3、Scheduler -> 调度器
- 4、Downloader -> 下载器
- 5、Scraoy Engine -> 核心引擎
Scrapy执行过程分析
- 1、Spider(我们编码的一个网站的爬虫) yield 一个 Request 出来,并发送给Engine(产生request,处理response)
- 2、Engine拿到Request以后发送给Scheduler(调度器)
- 3、Scheduler生成一个Requests交给Engine
- 4、Engine拿到 Scheduler的request后(注意是Scheduler发来的而不是Spider发来的),经过设置好的
DownloaderMiddleware,一步一步将Request送达Downloader - 5、Downloader下载网页后,再经过设置好的DownloaderMiddleware,一步一步将HttpResponse返回给Engine
- 6、Downloader拿到Response以后发送给Spiders进行处理分析(比如正则表达式,CSS选择器的配合使用提取网页字段)
- 7、Spider处理完的结果分为两类,一类是Item,一类是Request,这两类都会发给Engine,Engine拿到后判断如果是Items则会走8,如果是Requests则重复走2
- 8、Engine将Spiders发送过来的item发送给Item Piplines,将结果一步一步的Piplines将数据持久化到不同存储体里,比如JSON,Mysql,ES等
源码分析
Scrapy 核心的代码都在scrapy类库的scrapy/core文件夹下
Engine源码简析
...
# 此处为执行过程中1-2步,Engine拿到request后发送给Scheduler
def schedule(self, request, spider):
self.signals.send_catch_log(signal=signals.request_scheduled,
request=request, spider=spider)
# 调用scheduler的enqueue_request方法将request放到Scheduler中
if not self.slot.scheduler.enqueue_request(request):
self.signals.send_catch_log(signal=signals.request_dropped,
request=request, spider=spider)
...
...
# 此处为执行过程中第三步,从Engine中拿request给Scheduler
def _next_request_from_scheduler(self, spider):
slot = self.slot
request = slot.scheduler.next_request()
# 爬虫首次启动的时候先执行这个_next_request_from_scheduler方法,
# 但是scheduler里此时没有request,所以就会去从Spider中读取start_urls
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
...
...
Request类
Request类(由Spider产生)构造函数参数分析
class Request(object_ref):
# url: 请求参数
# callback:请求回调函数
# method: http请求类型
# headers: 请求头
# body:请求体
# cookies:浏览器cookie,自动登录后,scrapy会自动把cookie加入request中
# 该操作的实现是由scrapy.downloadermiddlewares.cookies.CookiesMiddleware的scrapy内置Middleware完成的
# meta:元信息,(可以在Request中传递)
# encoding:网页编码格式,默认UTF-8
# priority:设置在scheduler的调度优先级
# dont_filter:是否不过滤同时发出的相同request请求
# errback:失败的回调函数
#
def __init__(self, url, callback=None, method='GET', headers=None, body=None,
cookies=None, meta=None, encoding='utf-8', priority=0,
dont_filter=False, errback=None, flags=None):
转载文章:
scrapy进阶开发(一):scrapy架构源码分析
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)