Python程序员用的是同样是爬虫框架,为何Scrapy深受程序猿们喜爱
文末附有全套的python教学资料分享。
架构简介
下面是Scrapy的架构,包括组件以及在系统中发生的数据流的概览(红色箭头所示)。 之后会对每个组件做简单介绍,数据流也会做一个简要描述。
架构简介
组件
Engine: 引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。
Scheduler: 调度器从引擎接受Request并将他们入队,以便之后引擎请求他们时提供给引擎。
Downloader: 下载器负责获取页面数据并提供给引擎,而后提供给Spider。
Spiders: Spider是Scrapy用户编写的用于分析Response并提取Item或提取更多需要下载的URL的类。 每个Spider负责处理特定网站。
Item Pipeline: 负责处理被Spider提取出来的Item。典型的功能有清洗、 验证及持久化操作。
Downloader middlewares: 下载器中间件是在Engine及Downloader之间的特定钩子(specific hooks),处理Downloader传递给Engine的Response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。
Spider middlewares: 是在Engine及Spider之间的特定钩子(specific hook),处理Spider的输入(Response)和输出(Items及Requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。
数据流
Scrapy中的数据流由执行引擎控制,其过程如下:
1. Engine从Spider获取第一个需要爬取URL(s)。
2. Engine用Scheduler调度Requests,并向Scheduler请求下一个要爬取的URL。
3. Scheduler返回下一个要爬取的URL给Engine。
4. Engine将URL通过Downloader middlewares转发给Downloader。
5. 一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过Downloader middlewares发送给Engine。
6. 引擎从Downloader中接收到Response并通过Spider middlewares发送给Spider处理。
7. Spider处理Response并返回爬取到的Item及新的Request给Engine。
8. Engine将爬取到的Item给Item Pipeline,然后将Request给Scheduler。
9. 从第一步开始重复这个流程,直到Scheduler中没有更多的URLs。
架构就是这样,流程和我第二篇里介绍的迷你架构差不多,但扩展性非常强大。
One more thing
One more thing
Scrapy基于事件驱动网络框架 Twisted 编写,Twisted是一个异步非阻塞框架。一说到网络通信框架就会提什么同步、异步、阻塞和非阻塞,到底是些啥玩意啊?为啥老是有人暗示或者明示异步=非阻塞?比如Scrapy文档里:Scrapy is written with Twisted, a popular event-driven networking framework for Python. Thus, it’s implemented using a non-blocking (aka asynchronous) code for concurrency. 这种说法对吗?举个栗子:
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)
1. 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻。
2. 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3. 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大。
4. 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。
所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。
所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。
入门教程
创建项目
在开始爬取之前,您必须创建一个新的Scrapy项目。 进入您打算存储代码的目录中,运行下列命令:
scrapy startproject tutorial
该命令将会创建包含下列内容的 tutorial 目录:
编写第一个爬虫
Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。其包含了一个用于下载的初始URL,以及如何跟进网页中的链接以及如何分析页面中的内容的方法。
以下为我们的第一个Spider代码,保存在 tutorial/spiders 目录下的 quotes_spider.py文件中:
为了创建一个Spider,你必须继承 scrapy.Spider 类, 且定义以下三个属性:
1. name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
2. start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
3. parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据以及生成需要进一步处理的URL的 Request 对象。
运行我们的爬虫
进入项目的根目录,执行下列命令启动spider:
scrapy crawl quotes
这个命令启动用于爬取 quotes.toscrape.com 的spider,你将得到类似的输出:
提取数据
我们之前只是保存了HTML页面,并没有提取数据。现在升级一下代码,把提取功能加进去。至于如何使用浏览器的开发者模式分析网页,之前已经介绍过了。
再次运行这个爬虫,你将在日志里看到被提取出的数据:
保存爬取的数据
最简单存储爬取的数据的方式是使用 Feed exports:
该命令将采用 JSON 格式对爬取的数据进行序列化,生成quotes.json文件。
在类似本篇教程里这样小规模的项目中,这种存储方式已经足够。如果需要对爬取到的item做更多更为复杂的操作,你可以编写 Item Pipeline,tutorial/pipelines.py在最开始的时候已经自动创建了。