scrapy是使用python编写的高性能蜘蛛框架.
scrapinghub公司提供了基于云的蜘蛛平台, 也是开源项目scrapy后台支持的公司.
scrapy0.2x版本升级到1.x版本时, 将原有的scrapy部署服务拆分为独立的版本scrapyd.
这也是0.24版本和1.x版本不同之处.
scrapy的架构图如图1所示.
数据流的方向如下:
当蜘蛛启动的时候, 蜘蛛会处于空闲状态, 这时蜘蛛发出请求, 蜘蛛引擎向调度器请求爬取链接,
调度器发送链接, 蜘蛛引擎得到请求链接将其发送给下载器, 下载器下载链接指向的页面,
下载器将页面内容返回给蜘蛛引擎, 蜘蛛引擎将页面内容发送给蜘蛛, 蜘蛛处理页面之后,
将处理后的数据发送到数据管道, 从而完成一次页面的爬取.
蜘蛛启动时, 会读取自身设置的启动链接列表, 蜘蛛将启动链接列表发送给蜘蛛引擎,
蜘蛛引擎收到请求链接, 将其发送给调度器, 接着引擎向调度器请求下一个爬取的链接,
调度器根据自己的调度机制发出一条请求链接, 引擎获得请求链接, 经过下载中间件,
发送给下载器, 下载器下载到页面, 经过下载中间件发送给引擎, 引擎经过蜘蛛中间件发送给蜘蛛,
蜘蛛处理响应页面, 将新的合格链接经过蜘蛛中间件发送给引擎,
将提取的数据发送给数据管道, 数据管道将数据清洗并存储. 引擎从蜘蛛中得到新的请求链接,
将其发送给调度器, 不断循环, 直到所有的链接处理完.
这里就出现多个组建, 分别是蜘蛛引擎, 调度器, 下载器, 蜘蛛, 数据管道, 下载中间件
蜘蛛中间件.
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函数中将数据存入.
其他还有一些可以选择重写的函数:
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框架只是易碎的花瓶