# 13.4 Spider 的用法

在 Scrapy 中，要抓取网站的链接配置、抓取逻辑、解析逻辑里其实都是在 Spider 中配置的。在前一节实例中，我们发现抓取逻辑也是在 Spider 中完成的。本节我们就来专门了解一下 Spider 的基本用法。

### 1. Spider 运行流程

在实现 Scrapy 爬虫项目时，最核心的类便是 Spider 类了，它定义了如何爬取某个网站的流程和解析方式。简单来讲，Spider 要做的事就是如下两件。

* 定义爬取网站的动作
* 分析爬取下来的网页

对于 Spider 类来说，整个爬取循环如下所述。
* 以初始的 URL 初始化 Request，并设置回调函数。 当该 Request 成功请求并返回时，将生成 Response，并作为参数传给该回调函数。
* 在回调函数内分析返回的网页内容。返回结果可以有两种形式，一种是解析到的有效结果返回字典或 Item 对象。下一步可经过处理后（或直接）保存，另一种是解析得下一个（如下一页）链接，可以利用此链接构造 Request 并设置新的回调函数，返回 Request。
* 如果返回的是字典或 Item 对象，可通过 Feed Exports 等形式存入到文件，如果设置了 Pipeline 的话，可以经由 Pipeline 处理（如过滤、修正等）并保存。
* 如果返回的是 Reqeust，那么 Request 执行成功得到 Response 之后会再次传递给 Request 中定义的回调函数，可以再次使用选择器来分析新得到的网页内容，并根据分析的数据生成 Item。

通过以上几步循环往复进行，便完成了站点的爬取。

### 2. Spider 类分析

在上一节的例子中我们定义的 Spider 是继承自 scrapy.spiders.Spider，这个类是最简单最基本的 Spider 类，每个其他的 Spider 必须继承这个类，还有后文要说明的一些特殊 Spider 类也都是继承自它。

这个类里提供了 start_requests() 方法的默认实现，读取并请求 start_urls 属性，并根据返回的结果调用 parse() 方法解析结果。另外它还有一些基础属性，下面对其进行讲解：

* name，爬虫名称，是定义 Spider 名字的字符串。Spider 的名字定义了 Scrapy 如何定位并初始化 Spider，所以其必须是唯一的。 不过我们可以生成多个相同的 Spider 实例，这没有任何限制。 name 是 Spider 最重要的属性，而且是必须的。如果该 Spider 爬取单个网站，一个常见的做法是以该网站的域名名称来命名 Spider。 例如，如果 Spider 爬取 mywebsite.com ，该 Spider 通常会被命名为 mywebsite 。
* allowed_domains，允许爬取的域名，是可选配置，不在此范围的链接不会被跟进爬取。
* start_urls，起始 URL 列表，当我们没有实现 start_requests() 方法时，默认会从这个列表开始抓取。
* custom_settings，这是一个字典，是专属于本 Spider 的配置，此设置会覆盖项目全局的设置，而且此设置必须在初始化前被更新，所以它必须定义成类变量。
* crawler，此属性是由 from_crawler() 方法设置的，代表的是本 Spider 类对应的 Crawler 对象，Crawler 对象中包含了很多项目组件，利用它我们可以获取项目的一些配置信息，如最常见的就是获取项目的设置信息，即 Settings。
* settings，是一个 Settings 对象，利用它我们可以直接获取项目的全局设置变量。

除了一些基础属性，Spider 还有一些常用的方法，在此介绍如下：

* start_requests()，此方法用于生成初始请求，它必须返回一个可迭代对象，此方法会默认使用 start_urls 里面的 URL 来构造 Request，而且 Request 是 GET 请求方式。如果我们想在启动时以 POST 方式访问某个站点，可以直接重写这个方法，发送 POST 请求时我们使用 FormRequest 即可。
* parse()，当 Response 没有指定回调函数时，该方法会默认被调用，它负责处理 Response，处理返回结果，并从中提取出想要的数据和下一步的请求，然后返回。该方法需要返回一个包含 Request 或 Item 的可迭代对象。
* closed()，当 Spider 关闭时，该方法会被调用，在这里一般会定义释放资源的一些操作或其他收尾操作。

### 3. 结语

以上的介绍可能初看起来有点摸不清头脑，不过不用担心，后面我们会有很多实例来使用这些属性和方法，慢慢会熟练掌握的。