您的位置:首页 > 其它

scrapy源码阅读

2015-12-20 14:31 190 查看
scrapy是使用python编写的高性能蜘蛛框架.

scrapinghub公司提供了基于云的蜘蛛平台, 也是开源项目scrapy后台支持的公司.

scrapy0.2x版本升级到1.x版本时, 将原有的scrapy部署服务拆分为独立的版本scrapyd.

这也是0.24版本和1.x版本不同之处.

架构

scrapy的架构图如图1所示.



数据流的方向如下:

Spiders(蜘蛛)

Schediler(调度器)

Downloader(下载器)

Spiders(蜘蛛)

Item Pipeline(数据管道)

当蜘蛛启动的时候, 蜘蛛会处于空闲状态, 这时蜘蛛发出请求, 蜘蛛引擎向调度器请求爬取链接,

调度器发送链接, 蜘蛛引擎得到请求链接将其发送给下载器, 下载器下载链接指向的页面,

下载器将页面内容返回给蜘蛛引擎, 蜘蛛引擎将页面内容发送给蜘蛛, 蜘蛛处理页面之后,

将处理后的数据发送到数据管道, 从而完成一次页面的爬取.

蜘蛛启动时, 会读取自身设置的启动链接列表, 蜘蛛将启动链接列表发送给蜘蛛引擎,

蜘蛛引擎收到请求链接, 将其发送给调度器, 接着引擎向调度器请求下一个爬取的链接,

调度器根据自己的调度机制发出一条请求链接, 引擎获得请求链接, 经过下载中间件,

发送给下载器, 下载器下载到页面, 经过下载中间件发送给引擎, 引擎经过蜘蛛中间件发送给蜘蛛,

蜘蛛处理响应页面, 将新的合格链接经过蜘蛛中间件发送给引擎,

将提取的数据发送给数据管道, 数据管道将数据清洗并存储. 引擎从蜘蛛中得到新的请求链接,

将其发送给调度器, 不断循环, 直到所有的链接处理完.

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

蜘蛛中间件.

蜘蛛引擎 蜘蛛引擎负责控制数据流在系统中所有组件中流动, 并在相应动作发生时触发事件.

调度器 调度器从引擎接受请求将他们入队, 以便之后引擎请求他们时提供给引擎

下载器 下载器负责获取页面并提供给引擎, 而后提供给蜘蛛.

蜘蛛 蜘蛛是scrapy用户编写用于分析响应内容并提取数据或者额外链接的类

数据管道 数据管道处理被蜘蛛提取的数据. 一般进行清洗, 验证和持久化.

下载中间件 下载中间件是在引擎及其下载器之间的特定狗子, 处理下载器传递给引擎的相应内容.

蜘蛛中间件 蜘蛛中间件是在引擎及蜘蛛之间的特定钩子, 处理蜘蛛输入的相应和输出的请求及数据.

调度器

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框架只是易碎的花瓶
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: