姓名: 朱家骏
学号: 2017104145
日期: 2018.10.14
Scrapy是一个基于Python编写的一个开源爬虫框架,用途是从网上提取你所需要的数据 运行一个爬虫程序的步骤: 使用 scrapy startproject 创建爬虫模板,或者自己编写脚本程序 爬虫类继承scrapy.Spider,重写parse方法 Parse方法中yield或return dict、Request、Item 使用scrapy crawl<spider_name> 运行爬虫程序 Scrapy架构: 架构图 核心组件 Scrapy Engine:核心引擎,负责控制和调度各个组件,保证数据流转 Scheduler:负责管理任务、过滤任务、输出任务的调度器,存储、去重 Downloader:下载器,负责在网络上下载网页数据,输入待下载的URL,输出下载结果 Spiders:用户自己编写的爬虫脚本,可自定义抓取意图 Item Pipeline:负责输出结构化数据,可自定义输出位置 中间件组件: Downloader middlewares:介于引擎和下载器之间,可以在网页下载前、后进行逻辑处理 Spider middlewares:介于引擎和爬虫之间,可以在调用爬虫下载结果和输出请求时进行逻辑处理
数据流程 按照架构图的序号,数据流程如下: 1.引擎从自定义爬虫中获取初始化请求 2.引擎吧请求放入调度器中,同时引擎向调度器获取一个待下载的请求 3.调度器返回给引擎一个待下载的请求 4.引擎发送请求给下载器,中间会经过一系列下载器中间件 5.这个请求通过下载器下载后,生成一个响应对象,返回给引擎 6.引擎接收到下载返回的响应对象后,然后发送给爬虫,执行自定义爬虫逻辑 7.爬虫执行对应的回调方法,处理这个响应,完成用户逻辑后,会生成结果对象或新的请求对象给引擎 8.引擎把爬虫返回的结果对象交由结果处理器处理,把新的请求对象通过引擎在交给调度器 9.从1开始重复执行,知道调度器中没有新的请求处理
核心组件交互图 核心类图 Middleware middleware是嵌入Scrapy的爬行器处理机制的框架,可以插入自定义功能来处理发送给Spider进行处理的响应,以及处理从爬行器生成的请求和项目。 下载中间件
scrapy默认启动的下载中间件有 RobotsTxtMiddleware HttpAuthMiddleware DownloadTimeoutMiddleware UserAgentMiddleware RetryMiddleware DefaultHeadersMiddleware AjaxCrawlMiddleware MetaRefreshMiddleware HttpCompressionMiddleware RedirectMiddleware CookiesMiddleware HttpProxyMiddleware ChunkedTransferMiddleware DownloaderStats HttpCacheMiddleware
这些下载中间件使用相同的接口, 根据后边的数字依次调用. 也可以通过重写接口实现自定义中间件.
spider中间件: HttpErrorMiddleware:处理http错误, OffsiteMiddleware :处理离线网站, RefererMiddleware :处理referer表头, UrlLengthMiddleware :处理表头中url长度, DepthMiddleware :处理爬取深度
数据管道 scrapy自带三种数据管道, 用于处理三种不同的类型的数据, 分别是文件数据管道, 图片数据管道 文件数据管道用于处理文本数据, 将其存入文件,图片数据管道用于存储图片相关文件. 数据管道用于数据清洗与数据持久化.将数据清洗的数据管道设置更高的权限, 可以将脏数据转化为合格的数据, 或者是将其过滤. 数据持久化数据管道用于将数据存入数据库或者本地文件. 自定义数据管道时, 需要实现process_item函数, 当数据流向数据管道时, 会调用这个函数用于过滤数据, 和存储数据. 当用于数据持久化时, 一般重写构造函数, 在构造函数中创建文件操作对象或者数据库操作对象. 然后在process_item函数中将数据存入. 其他还有一些可以选择重写的函数: open_spider函数, 启动蜘蛛时调用. media_to_download函数用于检查下载前链接是否有问题. get_media_requests检查需要下载的媒体 media_downloaded处理成功下载的媒体 media_failed处理下载失败的媒体 item_completed当所有媒体都被处理完之后才被调用
调度器 scrapy的调度器的调度器包含四个组件: 去重组件, 内存队列, 磁盘队列, 状态收集组件. scrpay默认使用自带的去重组件为”RFPDupeFilter”(请求指纹重复过滤器). 这个组件通过python自带的set数据类型, 通过判断新请求链接是否在”集合”中, 来判断这个请求链接是否重复. 这个去重方式实现简单, 效率高, 但也出现了弊端.set集合是非线程安全数据结构, 因此不能使用于多线程情况.如果要scrapy改造成多线程或者多进程蜘蛛, 需要重写这个组件,因为这个组件是不支持多线程和多进程的. 其次, 这个去重组件使用的是set数据类型, 这个数据类型将所有的数据存储在内存中,当请求的链接过多的时候, 会出现内存不够问题, 因此, 这种去重组件仅仅是用于展示. 可以使用hashmap实现,使用链表的方式来实现。
scrapy的的内存队列和磁盘队列都是使用python第三方包”queuelib”中的内存队列和磁盘队列. 内存队列包括两种, 第一种是先进先出队列和先进后出队列, 前者是由队列后者是由栈实现. 磁盘队列包括两种持久化方法和两种队列类型. 持久化方法包括, pickle和marshal. 队列类型包括先进先出和先进后出队列, 即队列和栈.
启动调度器时, 调度器会读取配置中的”JOBDIR”设置. 如果这个变量不存在, 则不使用磁盘队列, 而内存队列不需要这个设置, 因此, 内存队列始终存在, 而磁盘队列只有在设置了”JOBDIR”这个变量之后才会使用.
引擎给调度器发送新的请求链接, 调度器判断该请求链接是否重复, 如果请求链接不重复, 先判断磁盘队列是否存在, 如果存在, 将其放在磁盘请求队列中, 如果不存在, 将其添加到内存磁盘请求队列中.
调度器重队列中取出请求链接时, 先从磁盘请求队列中取一个请求链接, 如果取得请求链接, 将其返回给蜘蛛引擎, 如果位取得请求链接, 调度器再向内存队列取链接, 将链接返回给蜘蛛队列.
这种队列方案, 当设置”JOBDIR”路径则使用磁盘请求队列, 不设置就使用内存队列, 可以灵活变更以适应不同的需求.
这种请求队列的设计模式一次只能使用一种队列, 即磁盘请求队列与内存请求队列无法同时使用.
内存请求队列速度快, 但是容量小. 磁盘请求队列容量大, 但是速度慢.
这种请求队列设计方案, 仍然面临无法实现分布式蜘蛛. 对于内存请求队列, 只能在单线程中使用, 无法实现分布式. 对于磁盘请求队列, scrapy并没有设置读写控制组件, 无法实现多线程或者多进程并发运行.
如果要实现分布式蜘蛛, 必须修改请求队列. 同样对于蜘蛛的状态收集器使用dict数据结构实现, 无法实现分布式数据共享, 因此需要实现分布式重写状态收集器. 项目结构: tutorial/ scrapy.cfg # 配置文件 tutorial/ #工程的Python模块,从这导入你的代码 init.py items.py # items定义文件 middlewares.py # 中间件文件 pipelines.py # 管道文件 settings.py # 设置文件 spiders/ # 爬虫文件夹 init.py
数据抓取实验: 源码: QuoteSpider.py
使用shell: scrapy crawl quotes -o quotes.json 输出文件: quotes.json