博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
scrapy进阶开发(一):scrapy架构源码分析
阅读量:6653 次
发布时间:2019-06-25

本文共 4350 字,大约阅读时间需要 14 分钟。

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文件夹下

(downloader 支持多种类型下载)

spider,pipline,middleware 是自己编写的

  • 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类(由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):复制代码
  • Response类(由Downloader产生)构造函数参数分析

class Response(object_ref):    # url 网页的url    # status 返回状态码,默认是200,代表成功    # headers 服务器返回的响应头    # body 返回的内容体    # request 之前yield的Request,对应的请求    def __init__(self, url, status=200, headers=None, body=b'', flags=None, request=None):        self.headers = Headers(headers or {})        self.status = int(status)        self._set_body(body)        self._set_url(url)        self.request = request        self.flags = [] if flags is None else list(flags)复制代码

其子类有HtmlResponse,TextResponse,XmlResponse

from scrapy.http.response.text import TextResponseclass HtmlResponse(TextResponse):    pass复制代码
class TextResponse(Response):    ...    ...    # Response内部已经引入了selector拱xpath,css方法调用    @property    def selector(self):        from scrapy.selector import Selector        if self._cached_selector is None:            self._cached_selector = Selector(self)        return self._cached_selector    # xpath 选择器    def xpath(self, query, **kwargs):        return self.selector.xpath(query, **kwargs)    # css 选择器    def css(self, query):        return self.selector.css(query)    ...    ...复制代码

转载地址:http://tunto.baihongyu.com/

你可能感兴趣的文章
数据结构-线性表-队列
查看>>
.net平台下C#socket通信(中)
查看>>
关于eclipse安装Genymotion插件的方法
查看>>
Java并发编程之闭锁CountDownLatch简单介绍
查看>>
Dnsmasq简介
查看>>
[AngularJS] Transforming raw JSON data to meaningful output in AngularJS
查看>>
HDU 1171 Big Event in HDU (多重背包变形)
查看>>
input placeholder属性IE、360浏览器兼容性问题
查看>>
iOS开发Swift篇—(十)方法
查看>>
DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样
查看>>
DNS 原理入门
查看>>
Netty学习笔记之一(Netty解析简单的Http Post Json 请求)
查看>>
Chrome 开发工具之Network
查看>>
CAS 单点登录流程
查看>>
VB.NET转C#代码的工具
查看>>
sqlServer数据库实现不同库之间表迁移
查看>>
移动端开发demo—移动端web相册(一)
查看>>
Decision tree(决策树)算法初探
查看>>
UltraISO 9.7.0.3476中文完美破解安装版
查看>>
Cesium随笔(3)随鼠标实时显示经纬度坐标以及高度【转】
查看>>