Scrapy框架介绍
Scrapy 是一个基于 Python 开发的爬虫框架,可以说它是当前 Python 爬虫生态中最流行的爬虫框架,该框架提供了非常多爬虫相关的基础组件:架构清晰,可扩展性极强。基于 Scrapy,我们可以灵活高效地完成各种爬虫需求。
本节会首先介绍 Scrapy 框架的基本架构和功能。
简介
在本章之前,我们大多是基于 requests 或 aiohttp 来实现爬虫的整个逻辑的。可以发现,在整个过程中,我们需要实现爬虫相关的所有操作,例如爬取逻辑,异常处理、数据解析、数据存储等,但其实这些步骤很多都是通用或者重复的。既然如此,我们完全可以把这些步骤的逻辑抽离出来,把其中通用的功能做成一个个基础的组件。
抽离出基础组件以后,我们每次写爬虫只需要在这些组件基础上加上特定的逻辑就可以实现爬取的流程了,而不用再把爬虫每个细小的流程都实现一遍。比如说我们想实现这样一个爬取逻辑:遇到服务器返回 403 状态码的时候就发起重试,遇到 404 状态码的时候就直接跳过。这个逻辑其实很多爬虫都是类似的,那么我们就可以把这个逻辑封装成一个通用的方法或类来直接调用,而不用每次都把这个过程再完整实现一遍,这就天大简化了开发成本,同时在慢慢积累的过程中,这个通用的方法或类也会变得越来越健壮,从而进一步保障了项目的稳定性,框架就是基于这种思想逐渐诞生出来的。
Scrapy 框架几乎是 Python 爬虫学习和工作过程中必须掌握的框架,需要好好钻研和掌握。 |
这里给出 Scrapy 框架的一些相关资源,包括官网、文档,GitHub 地址,建议不熟悉相关知识的读者在阅读之前览一下基本介绍。
架构
说了这么多,Scrapy 框架的功能到底强在哪里?组件丰富在哪里?扩展性好在哪里?不要着急,本章后文会逐一讲解它的功能和各个组件的用法。
首先从整体上看一下 Scrapy 框架的架构,如图 15-1 所示。

图 15-1 来源于 Scrapy 官方文档,初看上去可能比较复杂,下面我们来介绍一下。
-
Engine:图中最中间的部分,中文可以称为引擎,用来处理整个系统的数据流和事件,是整个框架的核心,可以理解为整个框架的中央处理器,负责数据的流转和逻辑的处理。
-
Item:它是一个抽象的数据结构,所以图中没有体现出来,它定义了爬取结果的数据结构,爬取的数据会被赋值成 Item 对象。每个 Item 就是一个类,类里面定义了爬取结果的数据字段,可以理解为它用来规定爬取数据的存储格式。
-
Scheduler:图中下方的部分,中文可以称为调度器,它用来接受 Engine 发过来的 Request 并将其加入队列中,同时也可以将 Request 发回给 Engine 供 Downloader 执行,它主要维护 Request 的调度逻辑,比如先进先出,先进后出、优先级进出等等。
-
Spiders:图中上方的部分,中文可以称为蜘蛛,Spiders 是一个复数统称,其可以对应多个 Spider,每个 Spider 里面定义了站点的爬取逻辑和页面的解析规则,它主要负责解析响应并生成 Item 和新的请求然后发给 Engine 进行处理。
-
Downloader:图中右侧部分,中文可以称为下载器,即完成 “向服务器发送请求,然后拿到响应” 的过程,得到的响应会再发送给 Engine 处理。
-
Item Pipelines:图中左侧部分,中文可以称为项目管道,这也是一个复数统称,可以对应多个 Item Pipeline。Item Pipeline 主要负责处理由 Spider 从页面中抽取的 Item,做一些数据清洗、验证和存储等工作,比如将 Item 的某些字段进行规整,将 Item 存储到数据库等操作都可以由 Item Pipeline 来完成。
-
Downloader Middlewares:图中 Engine 和 Downloader 之间的方块部分,中文可以称为下载器中间件,同样这也是复数统称,其包含多个 Downloader Middleware,它是位于 Engine 和 Downloader 之间的 Hook 框架,负责实现 Downloader 和 Engine 之间的请求和响应的处理过程。
-
Spider Middlewares:图中 Engine 和 Spiders 之间的方块部分,中文可以称为蜘蛛中间件,它是位于 Engine 和 Spiders 之间的 Hook 框架,负责实现 Spiders 和 Engine 之间的 Item,请求和响应的处理过程。
以上便是 Scrapy 中所有的核心组件,初看起来可能觉得非常复杂并且难以理解,但上手之后我们会慢慢发现其架构设计之精妙,后面让我们来一点点了解和学习
数据流
上文我们了解了 Scrapy 的基本组件和功能,通过图和描述我们可以知道,在整个爬虫运行的过程中,Engine 负责了整个数据流的分配和处理,数据流主要包括 Item,Request,Response 这三大部分,那它们又是怎么被 Engine 控制和流转的呢?
下面我们结合图 15-1 来对数据流做一个简单说明。
-
启动爬虫项目时,Engine 根据要爬取的目标站点找到处理该站点的 Spider,Spider 会生成最初需要爬取的页面对应的一个或多个 Request,然后发给 Engine。
-
Engine 从 Spider 中获取这些 Request,然后把它们交给 Scheduler 等待被调度。
-
Engine 向 Scheduler 索取下一个要处理的 Request,这时候 Scheduler 根据其调度逻辑选择合适的 Request 发送给 Engine。
-
Engine 将 Scheduler 发来的 Request 转发给 Downloader 进行下载执行,将 Request 发送给 Downloader 的过程会经由许多定义好的 Downloader Middlewares 的处理。
-
Downloader 将 Request 发送给目标服务器,得到对应的 Response,然后将其返回给 Engine。将 Response 返回 Engine 的过程同样会经由许多定义好的 Downloader Middlewares 的处理。
-
Engine 从 Downloder 处接收到的 Response 里包含了爬取的目标站点的内容,Engine 会将此 Response 发送给对应的 Spider 进行处理,将 Response 发送给 Spider 的过程中会经由定义好的 Spider Middlewares 的处理。
-
Spider 处理 Response,解析 Response 的内容,这时候 Spider 会产生一个或多个爬取结果 Item 或者后续要爬取的目标页面对应的一个或多个 Request,然后再将这些 Item 或 Request 发送给 Engine 进行处理,将 Item 或 Request 发送给 Engine 的过程会经由定义好的 Spider Middlewares 的处理。
-
Engine 将 Spider 发回的一个或多个 Item 转发给定义好的 Item Pipelines 进行数据处理或存储的一系列操作,将 Spider 发回的一个或多个 Request 转发给 Scheduler 等待下一次被调度。
重复第(2)步到第(8)步,直到 Scheduler 中没有更多的 Request,这时候 Engine 会关闭 Spider,整个爬取过程结束。
以上步骤介绍了爬虫执行过程中的数据流转过程,起初看起来确实比较复杂,但不用担心,后文我们会结合一些实战案例来慢慢理解这些过程。
从整体上看来,各个组件都只专注于一个功能,组件和组件之间的耦合度非常低,也非常容易扩展。再由 Engine 将各个组件组合起来,使得各个组件各司其职,互相配合:共同完成爬取工作。另外加上 Scrapy 对异步处理的支持,Scrapy 还可以最大限度地利用网络带宽,提高数据爬取和处理的效率。
项目结构
了解了 Scrapy 的基本架构和数据流过程之后,我们再来大致一看下其项目代码的整体架构是怎样的。
在这之前我们需要先安装 Scrapy 框架,一般情况下,使用 pip3 直接安装即可:
pip3 install scrapy
但 Scrapy 框架往往需要很多依赖库,如果依赖库没有安装好,Scrapy 的安装过程是比较容易失败的。如果安装有问题,可以参考 https://setup.scrape.center/scrapy 里面的详细说明。
安装成功之后,我们就可以使用 scrapy 命令行了,在命令行输入 scrapy 可以得到类似如下所示的结果。
~>scrapy
Scrapy 2.11.0 - no active project
Usage:
scrapy <command> [options] [args]
Available commands:
bench Run quick benchmark test
fetch Fetch a URL using the Scrapy downloader
genspider Generate new spider using pre-defined templates
runspider Run a self-contained spider (without creating a project)
settings Get settings values
shell Interactive scraping console
startproject Create new project
version Print Scrapy version
view Open URL in browser, as seen by Scrapy
[ more ] More commands available when run from project directory
Use "scrapy <command> -h" to see more info about a command
Scrapy 可以通过命令行来创建一个爬虫项目,比如我们要创建一个专门用来爬取新闻的项目,取名为 news,那么我们可以执行如下命令:
scrapy startproject news
这里我们使用 startproject 命令加上项目的名称就创建了一个名为 news 的 Scrapy 爬虫项目。执行完毕之后,当前运行目录下便会出现一个名为 news 的文件夹,该文件夹就对应一个 Scrapy 爬虫项目。
接着进入 news 文件夹,我们可以再利用命令行创建一个 Spider 用来专门爬取某个站点的新闻,比如新浪新闻,我们可以使用如下命令创建一个 Spider:
scrapy genspider sina news.sina.com.cn
这里我们利用 genspider 命令加上 Spider 的名称再加上对应的域名,成功创建了一个 Spider,这个 Spider 会对应一个 Python 文件,出现在项目的 spiders 目录下。
现在项目文件的结构如下:

在此将各个文件的功能描述如下。
-
scrapy.cfg:Scrapy 项目的配置文件,其中定义了项目的配置文件路径、部署信息等。
-
items.py:定义了 Item 数据结构,所有 Item 的定义都可以放这里。
-
pipelines.py:定义了 Item Pipeline 的实现,所有的 Item Pipeline 的实现都可以放在这里。
-
settings.py:定义了项目的全局配置。
-
middlewares.py:定义了 Spider Middlewares 和 Downloader Middlewares 的实现。
-
spiders:里面包含一个个 Spider 的实现,每个 Spider 都对应一个 Python 文件。
在此我们仅需要对这些文件的结构和用途做初步的了解,后文会对它们进行深人讲解。