一、Scrapy的定义
Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。【是纯python实现的框架】
二、Scrapy框架的安装
pip install scrapy
(有可能还需要安装其他的依赖库等【我安装时直接输入此命令进行安装的,中间有报错,但是还是重复此命令操作,最后安装好了】)
三、Scrapy框架的整体架构和组成
官方的Scrapy的架构图如下:
其中,图中绿色的是数据的流向。
1)架构说明:
》Scrapy Engine(引擎):负责Spiders
、ItemPipeline
、Downloader
、Schedule
中间的通讯,信号、数据传递等【处理整个系统的数据流处理,出发事物,框架的核心】。
》Scheduler(调度器):简单说就是队列。它负责接受引擎发送过来的Request
请求,并按照一定的方式进行整理排列,加入队列,在引擎再次请求时将请求提供给引擎。
》Downloader(下载器):负责下载Scrapy Engine(引擎)
发送的所有Requests
请求,并将其获取到的Responses
交还给Scrapy Engine(引擎)
,由引擎交给Spiders
来处理。
》Spiders(爬虫解析器):【编写xpath、正则表达式等解析策略,用于分析和处理数据】它负责处理所有Responses
,从中分析提取数据,获取Item
字段需要的数据;如果有新链接的请求(如下一页),将需要跟进的URL
提交给引擎,再次进入Scheduler(调度器)
。
》Item Pipeline(管道):它负责处理Spiders
中获取到的Item
,并进行后期处理(详细分析、过滤、存储等)的地方。
》Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件【封装代理、http头部隐藏等】。
》Spider Middlewares(Spider中间件):一个可以自定义扩展和操作引擎和Spiders
中间通信的功能组件。
2)结合下表概括了框架中各组件的作用:
3)梳理一下scrapy框架的整体执行流程:
1.Spiders
的 yeild 将 request 发送给Engine
【编写入口url(即需要请求的网站)】
2.Engine
对 request 不做任何处理,将 request 发送给Scheduler
,让它排序、入队列
3.Scheduler
排好队列后,将新的 request 请求发送给Engine
4.Engine
拿到新的 request 后,发送给Downloader
让它下载
5.Downloader
下载好后(即获取到response)之后,再发送回Engine
6.Engine
获取到response之后,返回给Spiders
,Spiders
的 parse() 方法对获取到的response进行处理,解析出 “items” 或者 "requests"
7.Spiders
将解析出来的 “items” 或者 “requests” 发送给Engine
8.Engine
获取到 “items” 或者 “requests” ,将 “items” 发送给ItemPipeline
;将 “requests” 发送给Scheduler
9.ItemPipeline
收到 “items” 后,对数据进行后期处理(详细分析、过滤、存储等)
10.Scheduler
收到 “requests” 后,对请求再进行排序、入队,再发送给Downloader
让它下载
scrapy框架是异步开发的,各个组件各司其职。
(ps:只有Scheduler
中不存在 request 时,程序才停止;如果Downloader
没有下载成功,则会返回给Engine
,让Scheduler
重新排列,再将新的 request 发送给Downloader
进行下载处理)
四、Scrapy框架的使用
1️⃣创建项目:scrapy startproject xxx
例如:
scrapy startproject tubatu_scrapy_project
2️⃣查看项目中的文件
①scrapy.cfg文件【项目的配置文件】,包含指定当前项目配置的路径(settings)、以及部署信息(deploy)
②项目文件下的items.py文件【定义数据结构】,即想要抓取哪些字段(例如名称、url等)
③项目文件下的pipelines.py文件【项目管道文件,又称数据处理管道文件】,用于编写数据的存储、清洗等逻辑。如将数据存储到json文件或mongo文件,就可以在此编写逻辑
④项目文件下的settings.py文件【项目设置文件】,可以定义项目的全局设置,一般用到哪个选项就开启并设置即可。(其中是否遵循ROBOTS协议这一项,一般设置为False)
⑤项目文件下的middlewares.py文件【定义了两个中间类的规则编写】,可以设置http的头部信息,设置代理等
⑥项目文件下的spiders文件夹【包含每个爬虫项目的实现】,解析规则就会写在此目录中,在spiders目录下编写爬虫逻辑(爬虫解析器)即可。而我们可以使用命令生成spider模板来直接编写爬虫逻辑,如下一步骤👇
3️⃣通过模板生成spider文件
cd到项目中的spiders目录,输入命令:scrapy genspider xxx(爬虫名) xxx.com (爬取网址的目标域名)
例如:scrapy genspider tubatu xiaoguotu.to8to.com/tuce/
创建后如下图所示:
该spider文件,继承自scrapy.Spider基类,且默认使用start_request
来发送请求,而start_request
方法会调用start_urls中的url
,它所返回的response
会默认使用parse()函数进行处理。
其中,
name就是爬虫项目名称;
allowed_domains就是指定允许爬取的域名;
start_urls就是指定从哪个url
地址开始抓取;
parse()函数就是默认的解析方法
4️⃣运行项目
当编写好爬虫文件后,执行爬虫开始抓取数据时,那么需要在命令行中输入:scrapy crawl xxx(爬虫项目名称)
,才能运行项目文件
例如:
scrapy crawl tubatu
!!!为了不每次都在命令行中输入该命令来运行项目,可以改用下面这种方法。
在项目文件下创建main.py文件,在里面编辑以下命令:
from scrapy import cmdline
cmdline.execute("scrapy crawl xxx".split()) # 其中xxx表示爬虫项目名称
如图所示:
👉保存项目
如果想保存为csv、xml、json
格式,可以直接使用命令:
在该文件夹下,按住shift-右键-在此处打开命令窗口,输入:(xxx表示项目名称)
scrapy crawl xxx -o xxx.csv
scrapy crawl xxx -o xxx.xml
scrapy crawl xxx -o xxx.json
选择其中一个即可。当然如果想要保存为其他格式也是可以的,这里只说常见的。这里选择json格式,运行后会发现,在文件夹下多出来一个xxx.json的文件。打开之后发现,中文都是一串乱码,这里需要修改编码方式,当然也可以在配置里修改:在settings.py文件中添加FEED_EXPORT_ENCODING='UTF8'
即可),
如果想直接在命令行中修改,输入如下命令即可:
scrapy crawl xxx -o xxx.json -s FEED_EXPORT_ENCODING=UTF8
后面实战还会讲解存储在mongodb数据库的方法
五、其他要点
1)scrapy中使用xpath的extract()
和extract_first()
的区别
scrapy爬虫框架中,因为response
就是一个Html对象
,所以response
后面可以直接使用xpath方法,而不需要去导入lxml库等。
在使用scrapy爬虫的时候,我们常常使用xpath来获取html标签。但是我们经常会用到提取的方法,有两种提取的方法,分别是:
》
extract()
:这个方法返回的是一个数组list,里面包含了多个string,如果只有一个string,则返回[‘ABC’]这样的形式。
》
extract_first()
:这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
2)scrapy中 yield
的使用详解
如下图所示代码(一共使用3次yield
)【该代码是通过scrapy框架来爬小说网站】:
- 第一次:
》这里我们在循环里爬取小说详细页面的链接,并通过yield
来发起异步请求,并且还将函数getInfo
作为回调函数来从响应中提取所需要的数据(注意,该回调函数只写函数的名称即可)❗ - 第二次:
》这里是在爬取完一页的信息后,我们在当前页面获取到了下一页的链接,然后通过yield
发起异步请求,并且将parse
自己作为回调函数来处理下一页的响应(注意,该回调函数只写函数的名称即可)❗ - 第三次:
》这里我们通过yield
返回的不是Request对象
,而是一个TextInfoItem对象
。
scrapy框架 获得这个对象之后,会将这个对象传递给 pipelines.py来做进一步处理。我们可以在 pipelines.py里将传递过来的 scrapy.Item 对象保存到数据库里去❗
总结:
scrapy框架 会根据 yield
返回的实例类型来执行不同的操作,
》如果是 scrapy.Request 对象
,scrapy框架 会去获得该对象指向的链接并在请求完成后调用该对象的回调函数。
》如果是 scrapy.Item 对象
,scrapy框架 会将这个对象传递给 pipelines.py做进一步处理。
【该yield的使用讲解,参考该链接:https://www.jianshu.com/p/7c1a084853d8】