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. 结语

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

Last updated