scrapy源码阅读

原创 2015年12月20日 14:31:19

scrapy是使用python编写的高性能蜘蛛框架.
scrapinghub公司提供了基于云的蜘蛛平台, 也是开源项目scrapy后台支持的公司.
scrapy0.2x版本升级到1.x版本时, 将原有的scrapy部署服务拆分为独立的版本scrapyd.
这也是0.24版本和1.x版本不同之处.

架构

scrapy的架构图如图1所示.
图1

数据流的方向如下:

  1. Spiders(蜘蛛)
  2. Schediler(调度器)
  3. Downloader(下载器)
  4. Spiders(蜘蛛)
  5. Item Pipeline(数据管道)

当蜘蛛启动的时候, 蜘蛛会处于空闲状态, 这时蜘蛛发出请求, 蜘蛛引擎向调度器请求爬取链接,
调度器发送链接, 蜘蛛引擎得到请求链接将其发送给下载器, 下载器下载链接指向的页面,
下载器将页面内容返回给蜘蛛引擎, 蜘蛛引擎将页面内容发送给蜘蛛, 蜘蛛处理页面之后,
将处理后的数据发送到数据管道, 从而完成一次页面的爬取.

蜘蛛启动时, 会读取自身设置的启动链接列表, 蜘蛛将启动链接列表发送给蜘蛛引擎,
蜘蛛引擎收到请求链接, 将其发送给调度器, 接着引擎向调度器请求下一个爬取的链接,
调度器根据自己的调度机制发出一条请求链接, 引擎获得请求链接, 经过下载中间件,
发送给下载器, 下载器下载到页面, 经过下载中间件发送给引擎, 引擎经过蜘蛛中间件发送给蜘蛛,
蜘蛛处理响应页面, 将新的合格链接经过蜘蛛中间件发送给引擎,
将提取的数据发送给数据管道, 数据管道将数据清洗并存储. 引擎从蜘蛛中得到新的请求链接,
将其发送给调度器, 不断循环, 直到所有的链接处理完.

这里就出现多个组建, 分别是蜘蛛引擎, 调度器, 下载器, 蜘蛛, 数据管道, 下载中间件
蜘蛛中间件.

  1. 蜘蛛引擎 蜘蛛引擎负责控制数据流在系统中所有组件中流动, 并在相应动作发生时触发事件.
  2. 调度器 调度器从引擎接受请求将他们入队, 以便之后引擎请求他们时提供给引擎
  3. 下载器 下载器负责获取页面并提供给引擎, 而后提供给蜘蛛.
  4. 蜘蛛 蜘蛛是scrapy用户编写用于分析响应内容并提取数据或者额外链接的类
  5. 数据管道 数据管道处理被蜘蛛提取的数据. 一般进行清洗, 验证和持久化.
  6. 下载中间件 下载中间件是在引擎及其下载器之间的特定狗子, 处理下载器传递给引擎的相应内容.
  7. 蜘蛛中间件 蜘蛛中间件是在引擎及蜘蛛之间的特定钩子, 处理蜘蛛输入的相应和输出的请求及数据.

调度器

scrapy的调度器的调度器包含四个组件: 去重组件, 内存队列, 磁盘队列, 状态收集组件.

scrpay默认使用自带的去重组件为”RFPDupeFilter”(请求指纹重复过滤器).
这个组件通过python自带的set数据类型, 通过判断新请求链接是否在”集合”中,
来判断这个请求链接是否重复.
这个去重方式实现简单, 效率高, 但也出现了弊端.

set集合是非线程安全数据结构, 因此不能使用于多线程情况.
如果要scrapy改造成多线程或者多进程蜘蛛, 需要重写这个组件,
因为这个组件是不支持多线程和多进程的.

其次, 这个去重组件使用的是set数据类型, 这个数据类型将所有的数据存储在内存中,
当请求的链接过多的时候, 会出现内存不够问题, 因此, 这种去重组件仅仅是用于展示.

scrapy的的内存队列和磁盘队列都是使用python第三方包”queuelib”中的内存队列和磁盘队列.

内存队列包括两种, 第一种是先进先出队列和先进后出队列, 前者是由队列后者是由栈实现.
磁盘队列包括两种持久化方法和两种队列类型.

持久化方法包括, pickle和marshal.
队列类型包括先进先出和先进后出队列, 即队列和栈.

启动调度器时, 调度器会读取配置中的”JOBDIR”设置.
如果这个变量不存在, 则不使用磁盘队列, 而内存队列不需要这个设置,
因此, 内存队列始终存在, 而磁盘队列只有在设置了”JOBDIR”这个变量之后才会使用.

引擎给调度器发送新的请求链接, 调度器判断该请求链接是否重复,
如果请求链接不重复, 先判断磁盘队列是否存在, 如果存在, 将其放在磁盘请求队列中,
如果不存在, 将其添加到内存磁盘请求队列中.

调度器重队列中取出请求链接时, 先从磁盘请求队列中取一个请求链接,
如果取得请求链接, 将其返回给蜘蛛引擎,
如果位取得请求链接, 调度器再向内存队列取链接, 将链接返回给蜘蛛队列.

这种队列方案, 当设置”JOBDIR”路径则使用磁盘请求队列, 不设置就使用内存队列,
可以灵活变更以适应不同的需求.

然而这种方式, 仍然缺点重重.

这种请求队列的设计模式一次只能使用一种队列, 即磁盘请求队列与内存请求队列无法同时使用.

内存请求队列速度快, 但是容量小.
磁盘请求队列容量大, 但是速度慢.

这种请求队列设计方案, 仍然面临无法实现分布式蜘蛛.

对于内存请求队列, 只能在单线程中使用, 无法实现分布式.
对于磁盘请求队列, scrapy并没有设置读写控制组件, 无法实现多线程或者多进程并发运行.

如果要实现分布式蜘蛛, 必须修改请求队列.

同样对于蜘蛛的状态收集器使用dict数据结构实现,
无法实现分布式数据共享, 因此需要实现分布式重写状态收集器.

蜘蛛

scrapy的蜘蛛分为feed蜘蛛, sitemap蜘蛛, 爬虫, 普通蜘蛛.

feed蜘蛛, sitemap蜘蛛和蜘蛛都继承自基类蜘蛛.
feed蜘蛛分为XMLFeedSpider, CSVFeedSpider, 分别用于爬取基于xml和csv的feed链接.
sitemap蜘蛛用于爬取网站的sitemap文件.
爬虫是对蜘蛛的改进, 使其更加适应方便高效.

蜘蛛中提供三个基本函数, 分别是start_requests函数,make_requests_from_url函数和 parse函数.

start_requests函数会在蜘蛛启动的时候被调用, 用于读取启动请求链接, 启动整个蜘蛛爬取网站数据.

对于一些需要登陆的网站, 例如知乎等, 需要登陆才能浏览页面的网站,
可以重写这个函数, 递交表单模拟登陆, 实现爬取动作.

make_requests_from_url函数用于在解析数据时, 将重新生成的链接加入爬取队列中.

parse函数是蜘蛛的默认回调函数, 用于请求从蜘蛛引擎收到响应页面时, 调用蜘蛛的函数.
重写这个函数用于解析响应页面的内容.

爬虫中对这种方案进行的修改, 引入了rules, 将需要爬取的链接的模式收集在一起,
直接由框架自行收集, 不再需要在parse函数中手动解析.

scrapy提供三种手段用于解析响应页面, 分别是xpath, css选择器和正则表达式.
当然, 也可以引入其他的解析工具, 比如beautifulsoap.

下载器

官方文档中提到使用twisted实现, 由于不太熟悉twisted框架, 并没有仔细研读.

数据管道

scrapy自带三种数据管道, 用于处理三种不同的类型的数据, 分别是文件数据管道, 图片数据管道和S3数据管道.

文件数据管道用于处理文本数据, 将其存入文件, S3数据管道用于将存储存入亚马逊的S3中.
图片数据管道用于存储图片相关文件.

数据管道用于数据清洗与数据持久化.

将数据清洗的数据管道设置更高的权限, 可以将脏数据转化为合格的数据,
或者是将其过滤.

数据持久化数据管道用于将数据存入数据库或者本地文件.

自定义数据管道时, 需要实现process_item函数,
当数据流向数据管道时, 会调用这个函数用于过滤数据, 和存储数据.

当用于数据持久化时, 一般重写构造函数, 在构造函数中创建文件操作对象或者数据库操作对象.
然后在process_item函数中将数据存入.

其他还有一些可以选择重写的函数:

  • open_spider函数, 启动蜘蛛时调用.
  • media_to_download函数用于检查下载前链接是否有问题.
  • get_media_requests检查需要下载的媒体
  • media_downloaded处理成功下载的媒体
  • media_failed处理下载失败的媒体
  • item_completed当所有媒体都被处理完之后才被调用

下载中间件

scrapy默认启动的下载中间件有
,RobotsTxtMiddleware
,HttpAuthMiddleware
,DownloadTimeoutMiddleware
,UserAgentMiddleware
,RetryMiddleware
,DefaultHeadersMiddleware
,AjaxCrawlMiddleware
,MetaRefreshMiddleware
,HttpCompressionMiddleware
,RedirectMiddleware
,CookiesMiddleware
,HttpProxyMiddleware
,ChunkedTransferMiddleware
,DownloaderStats
,HttpCacheMiddleware

这些下载中间件使用相同的接口, 根据后边的数字依次调用.
也可以通过重写接口实现自定义中间件.

蜘蛛中间件

scrapy默认的中间件有一下五种:
HttpErrorMiddleware用于处理http错误,
OffsiteMiddleware 用于处理离线网站,
RefererMiddleware 用于处理referer表头,
UrlLengthMiddleware 用于处理表头中url长度,
DepthMiddleware 用于处理爬取深度

蜘蛛引擎

无心继续阅读

总结

scrapy框架只是易碎的花瓶

相关文章推荐

scrapy源码分析(七)------------ Crawler

上一节讲了CrawlProcess的实现,讲了一个CrawlProcess可以控制多个Crawler来同时进行多个爬取任务,CrawlProcess通过调用Crawler的crawl方法来进行爬取,并...

scrapy启动过程源码分析

从源码理解scrapy的5大核心模块的实现。

Scrapy源码分析-所有爬虫的基类-Spider(二)

Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(...

Scrapy阅读源码分析<二>

scrapy命令 当用scrapy写好一个爬虫后,使用scrapy crawl 命令就可以运行这个爬虫,那么这个过程中到底发生了什么? scrapy命令从何而来? 实际上,当你成功安...

【原创】开源爬虫Scrapy的学习及应用

开源爬虫Scrapy的学习及应用作者:swb (360电商技术组)  一、 背景目前我们正在使用的一套爬虫框架是使用java开发的一套复杂的分布式电商垂直爬虫,它主要优点是流程完善、可用性高、易部署。...

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数

给定A, B两个整数,不使用除法和取模运算,求A/B的商和余数。 1.   最基本的算法是,从小到大遍历: for (i = 2 to A -1)          if (i * B > A)...

利用K-means聚类算法根据经纬度坐标对中国省市进行聚类

K-means聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其相似度就越高。程序读取全国省市经纬度坐标,然后根据经纬度坐标进...

Radon变换理论介绍与matlab实现--经验交流

本人最近在研究Radon变换,在查阅了各种资料之后在此写下个人的理解,希望与各位牛牛进行交流共同进步,也使得理解更加深刻些。 Radon变换的本质是将原来的函数做了一个空间转换,即,将原来的XY平...

CT图像重建技术

由于csdn贴图不方便,并且不能上传附件,我把原文上传到了资源空间CT图像重建技术 1.引言 计算机层析成像(Computed Tomography,CT)是通过对物体进行不同角度的射线投影测量而...

Matlab绘图-很详细,很全面

Matlab绘图强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数。此外,Ma...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:scrapy源码阅读
举报原因:
原因补充:

(最多只允许输入30个字)