Python爬虫 6.Scrapy 框架基础


一、为什么要学习 Scrapy

在前面的章节中,我们已经学习了如何使用 urllibrequests 发送请求,也学习了如何通过 XPath、BeautifulSoup 解析网页内容,还了解了 Selenium 在动态页面中的使用方式。

这些工具本身都很重要,但是当爬虫任务逐渐复杂时,问题也会越来越明显。

例如:

  • 需要抓取的网站页面数量越来越多
  • 需要同时管理很多请求
  • 需要把提取出来的数据统一处理和保存
  • 需要对爬虫的运行流程进行统一配置

如果继续使用普通 Python 脚本把这些逻辑全部写在一起,代码通常会出现几个问题:

  • 请求、解析、保存混在一起
  • 项目结构不清晰
  • 后续维护成本高
  • 想扩展新功能时不方便

这时,就需要一个专门用于组织爬虫流程的框架。

Scrapy 的作用就是把“发送请求、调度请求、解析响应、处理数据、扩展功能”这一整套流程组织起来,让我们能够用更工程化的方式来开发爬虫。

可以简单理解为:

  • requests 更适合写单个请求脚本
  • Scrapy 更适合写结构清晰、流程完整的爬虫项目

因此,当你已经具备基本的请求与解析能力后,继续学习 Scrapy 是非常自然的一步。


二、Scrapy 是什么

Scrapy 是 Python 中一个非常经典的爬虫框架。

它的定位不是“一个简单的请求库”,而是:

一套完整的爬虫开发框架。

它不仅仅能帮我们发送请求,还能够管理整个爬虫项目中的多个环节,例如:

  • 请求调度
  • 页面下载
  • 数据解析
  • 数据清洗
  • 数据存储
  • 中间件扩展

也就是说,当我们使用 Scrapy 时,不是在写“零散的爬虫脚本”,而是在开发一个有固定结构的爬虫项目。

Scrapy 特别适合下面这些场景:

  • 需要抓取大量页面
  • 需要持续发送很多请求
  • 需要统一管理数据输出
  • 需要多人协作开发爬虫项目

它的优势主要体现在:

  • 项目结构清晰
  • 运行流程规范
  • 自带调度机制
  • 易于扩展

所以学习 Scrapy,本质上是在学习如何把爬虫从“脚本级别”提升到“项目级别”。


三、安装 Scrapy

Scrapy 是第三方库,因此在使用之前需要先安装。

pip install scrapy

这条命令的作用是:

  • 从 Python 包管理器中下载 Scrapy
  • 安装 Scrapy 及其依赖组件
  • 让当前 Python 环境能够使用 scrapy 命令

安装完成后,可以在终端中执行下面的命令来检查是否安装成功:

scrapy version

如果终端能够正常输出版本号,就说明 Scrapy 已经安装成功。

如果安装完成后命令无法识别,通常需要检查:

  • Python 环境是否正确
  • pip 是否安装到了当前正在使用的解释器中
  • 环境变量是否配置正确

在实际使用中,建议优先确认两件事:

  1. pip install scrapy 是否执行成功
  2. scrapy version 是否能输出版本号

只要这两步没问题,通常就可以继续后面的学习。


四、创建第一个 Scrapy 项目

Scrapy 不是直接在一个 .py 文件里随便写代码就可以,而是先创建一个项目目录。

创建项目的命令如下:

scrapy startproject 项目名

例如:

scrapy startproject scrapy_test

执行之后,Scrapy 会自动帮我们生成一套标准项目结构。

这一步非常重要,因为 Scrapy 的很多配置、爬虫文件、数据处理逻辑,都是依赖这个项目结构来组织的。

创建完成后,你会得到一个新的项目目录,里面已经包含:

  • 配置文件
  • 爬虫目录
  • 数据结构文件
  • 数据处理文件
  • 中间件文件

也就是说,startproject 的作用不是“创建一个空文件夹”,而是:

直接帮我们生成一个完整的 Scrapy 项目模板。

这和我们之前写普通 Python 脚本的方式不同。Scrapy 更强调“先有项目,再在项目中编写爬虫”。


五、项目结构说明

Scrapy 项目创建好之后,最重要的一件事就是先看懂项目目录结构。

一个典型的 Scrapy 项目中,常见文件和目录包括:

  • spiders/:存放爬虫文件
  • items.py:定义数据结构
  • pipelines.py:处理数据
  • middlewares.py:中间件
  • settings.py:配置文件

下面分别说明它们的作用。

1. spiders/

这个目录用来存放具体的爬虫文件。

也就是说:

  • 一个项目可以有多个爬虫
  • 每个爬虫通常写在 spiders/ 目录下

例如:

  • 抓取新闻的爬虫
  • 抓取商品的爬虫
  • 抓取招聘信息的爬虫

都可以放在这个目录中。

2. items.py

items.py 的作用是定义数据结构。

在 Scrapy 中,我们通常不会一上来就用普通字典随便保存数据,而是先定义一个 Item,让数据的字段更明确。

例如:

  • 标题
  • 价格
  • 链接
  • 发布时间

这样做的好处是:

  • 结构清晰
  • 字段统一
  • 更适合后续处理和保存

3. pipelines.py

pipelines.py 用来处理爬虫提取到的数据。

常见用途包括:

  • 清洗数据
  • 去掉空值
  • 格式统一
  • 保存到文件
  • 保存到数据库

可以把它理解为:

数据在真正输出之前的“加工处理环节”。

在 Scrapy 中,Pipeline 是可以配置优先级的。

一般会在 settings.py 中启用,例如:

ITEM_PIPELINES = {
    'scrapy_test.pipelines.ScrapyTestPipeline': 300,
}

这里的数字表示执行优先级:

  • 数值越小,越先执行
  • 数值越大,越后执行

这样做的意义是:当一个项目中存在多个 Pipeline 时,可以控制它们的处理顺序。

4. middlewares.py

middlewares.py 是中间件文件。

它主要用于对请求和响应过程进行扩展控制,例如:

  • 请求头处理
  • 代理设置
  • 用户代理切换
  • 特殊请求逻辑

入门阶段不需要一开始就掌握太深,但要知道:

它是 Scrapy 提供给开发者的一个扩展入口。

5. settings.py

settings.py 是配置文件。

很多全局设置都在这里完成,例如:

  • 是否遵守 robots 协议
  • 下载延迟时间
  • 是否启用 Pipeline
  • 请求头设置
  • 编码设置

统一管理整个爬虫项目的配置。

例如,比较常见的配置有:

  • ROBOTSTXT_OBEY:是否遵守 robots 协议
  • USER_AGENT:请求头中的用户代理
  • DOWNLOAD_DELAY:下载延迟时间
  • ITEM_PIPELINES:启用哪些 Pipeline

因此,很多全局行为都不是写在 Spider 代码里,而是在 settings.py 中统一控制。


六、创建爬虫文件

在 Scrapy 项目中,具体的抓取逻辑通常写在 Spider 文件里。

Scrapy 提供了一个快速创建爬虫文件的命令:

scrapy genspider 爬虫名 域名

例如:

scrapy genspider baidu www.baidu.com

执行之后,Scrapy 会在 spiders/ 目录下自动生成一个基础爬虫文件。

一个最基本的 Spider 通常会包含下面几个部分:

  • name:爬虫名称
  • allowed_domains:允许访问的域名
  • start_urls:起始 URL
  • parse():解析函数

下面分别说明。

1. name

name 是爬虫名称。

它的作用主要是:

  • 作为爬虫的唯一标识
  • 在运行命令时使用

例如:

scrapy crawl baidu

这里的 baidu,就是爬虫文件中的 name

2. allowed_domains

allowed_domains 用来限制爬虫允许访问的域名范围。

这样做的目的是防止爬虫在跟踪链接时跑到不相关的网站中去。

3. start_urls

start_urls 是爬虫启动时首先要访问的页面列表。

Scrapy 会从这些起始页面开始发送请求。

4. parse()

parse() 是默认的解析函数,也是最核心的函数之一。

它的作用是:

  • 接收下载后的响应对象 response
  • 从响应中提取数据
  • 返回数据或新的请求

例如,最简单的写法如下:

import scrapy


class BaiduSpider(scrapy.Spider):
    name = 'baidu'
    allowed_domains = ['www.baidu.com']
    start_urls = ['https://www.baidu.com']

    def parse(self, response):
        print(response.text)

在这个例子中:

  • response 是服务器返回的响应对象
  • response.text 是页面文本内容

除了 response.text,在 Scrapy 中我们还常用:

  • response.body:字节数据
  • response.xpath():使用 XPath 提取内容
  • response.css():使用 CSS 选择器提取内容

在实际提取数据时,还经常会配合下面两个方法使用:

  • extract():把 Selector 对象中的内容提取出来,通常返回列表
  • extract_first():提取第一个结果,如果没有结果,通常返回空值

例如:

# 提取所有 title 文本
result = response.xpath('//title/text()').extract()
print(result)

# 只提取第一个 title 文本
first_result = response.xpath('//title/text()').extract_first()
print(first_result)

这两个方法在旧版 Scrapy 教程中非常常见,阅读资料时经常会遇到。

这说明:

Scrapy 的 response 本质上就是“请求结果 + 解析入口”的结合体。


七、运行 Scrapy 爬虫

Scrapy 项目和爬虫文件都准备好之后,就可以运行爬虫了。

运行命令如下:

scrapy crawl 爬虫名

例如:

scrapy crawl baidu

执行这条命令后,Scrapy 会自动完成下面这些步骤:

  1. 找到对应名称的爬虫
  2. 读取项目配置
  3. 发送起始请求
  4. 获取响应内容
  5. 调用 parse() 函数解析数据
  6. 处理提取结果

也就是说,运行 scrapy crawl 时,并不是单纯执行一个函数,而是:

启动整个 Scrapy 的运行流程。

因此在终端中通常会看到很多日志信息,例如:

  • 爬虫启动信息
  • 请求发送信息
  • 响应状态码
  • 数据处理信息
  • 爬虫结束信息

这些日志非常有助于排查问题和观察爬虫执行过程。


八、Scrapy 工作原理

Scrapy 的学习难点之一,就是很多初学者只会写代码,但不理解它内部的运行流程。

实际上,Scrapy 的整个工作过程可以理解为一条完整的流水线。

核心组件包括:

  • 引擎(Engine)
  • 调度器(Scheduler)
  • 下载器(Downloader)
  • Spider
  • Pipeline

下面按流程解释它们的作用。

1. 引擎(Engine)

引擎是 Scrapy 的核心调度中心。

它负责协调各个模块之间的工作,例如:

  • 把请求交给调度器
  • 把调度器返回的请求交给下载器
  • 把下载器返回的响应交给 Spider
  • 把 Spider 提取的数据交给 Pipeline

可以把引擎理解为:

整个框架的总指挥。

2. 调度器(Scheduler)

调度器负责管理所有待发送的请求。

它的主要任务是:

  • 接收新的请求
  • 排队管理请求
  • 决定下一个该处理哪个请求

因此,调度器本质上管理的是“请求队列”。

3. 下载器(Downloader)

下载器负责真正向目标网站发送请求,并获取响应内容。

也就是说:

  • 请求到了下载器这里,才会真的发出去
  • 响应回来了,下载器再把它交给引擎

4. Spider

Spider 是我们自己编写爬虫逻辑的地方。

它的主要工作是:

  • 接收响应
  • 提取数据
  • 生成新的请求

所以 Spider 的核心职责不是“下载页面”,而是“解析页面”。

5. Pipeline

Pipeline 负责对 Spider 提取出的数据进行进一步处理。

例如:

  • 清洗字段
  • 去重
  • 保存到 JSON
  • 保存到数据库

6. 基本流程理解

可以把 Scrapy 的整体流程理解为:

引擎 → 调度器 → 下载器 → 引擎 → Spider → Pipeline

或者更直白一点:

  1. Spider 提供初始请求
  2. 调度器管理请求
  3. 下载器发送请求并下载页面
  4. Spider 解析页面
  5. Pipeline 处理数据

只要把这条主线理解清楚,Scrapy 的整体逻辑就会清晰很多。


九、scrapy shell 的使用

scrapy shell 是 Scrapy 中非常实用的调试工具。

它的作用是:

在不运行完整爬虫的情况下,单独测试某个页面的解析表达式。

使用方式如下:

scrapy shell url

例如:

scrapy shell https://www.baidu.com

执行后,Scrapy 会打开一个交互式环境,并自动请求该页面。

在这个环境里,我们就可以直接使用 response 来测试提取逻辑。

例如:

response.text
response.xpath('//title/text()').extract()
response.css('title::text').extract()

除了上面这些最常用的操作,在 shell 中还可以查看:

response.body
response.url
response.status

分别表示:

  • response.body:字节形式的响应内容
  • response.url:当前响应对应的地址
  • response.status:HTTP 状态码

另外,通过 XPath 或 CSS 获取到的通常是 SelectorSelectorList 对象,它们还可以继续调用:

response.xpath('//title')
response.xpath('//title').extract()
response.css('title::text').extract_first()

这说明:

  • response.xpath()response.css() 负责“定位元素”
  • extract()extract_first() 负责“把结果真正取出来”

scrapy shell 的价值非常高,因为它可以帮助我们:

  • 先验证 XPath 是否正确
  • 先验证 CSS 选择器是否正确
  • 提前检查页面结构
  • 减少正式运行爬虫时的试错成本

因此,在实际开发中,很多 Scrapy 爬虫都是先用 scrapy shell 调试解析逻辑,再写进 Spider 文件中。

如果本地安装了 ipython,那么 scrapy shell 的交互体验通常会更好,例如补全和输出显示会更方便。

安装方式如下:

pip install ipython

这不是必须步骤,但在调试时会更舒服一些。


十、yield 的作用

在 Scrapy 中,yield 是一个非常高频出现的关键字。

很多初学者第一次接触 Scrapy 时,都会看到两种写法:

  • yield item
  • yield scrapy.Request(...)

要理解它,先要明白:

yield 在 Python 中表示“逐个返回结果”,而不是一次性全部返回。

在 Scrapy 里,这种机制非常适合爬虫流程,因为:

  • 爬虫可能会不断地产生数据
  • 爬虫也可能不断地产生新的请求

1. yield item

当 Spider 成功提取到一条数据后,可以使用:

yield item

这表示:

  • 把当前提取到的数据交给后续流程处理
  • 数据通常会流向 Pipeline

2. yield scrapy.Request(…)

当 Spider 在解析当前页面时,发现了新的页面链接,还可以继续生成新的请求:

yield scrapy.Request(url=next_url, callback=self.parse)

这表示:

  • 继续请求新的页面
  • 请求完成后,再交给指定的回调函数处理

因此,在 Scrapy 中,yield 的作用可以总结为:

  • 返回数据
  • 派发新的请求

这也是 Scrapy 能够持续抓取多个页面的重要原因。


十一、Item 与 Pipeline

这两个模块通常是 Scrapy 入门时必须理解的部分。

1. Item 是什么

Item 的作用是定义数据结构。

例如,我们要抓取一个商品页面,可能希望保存这些字段:

  • 商品标题
  • 商品价格
  • 商品链接

这时,就可以在 items.py 中定义:

import scrapy


class ProductItem(scrapy.Item):
    title = scrapy.Field()
    price = scrapy.Field()
    url = scrapy.Field()

这样做的好处是:

  • 字段清晰
  • 数据结构规范
  • 更方便后续处理

2. Pipeline 是什么

Pipeline 用于处理 Spider 提取到的数据。

例如,在 pipelines.py 中,我们可以写:

class ScrapyTestPipeline:
    def process_item(self, item, spider):
        print(item)
        return item

process_item() 的作用是:

  • 接收 Spider 传来的数据
  • 对数据进行处理
  • 返回处理后的数据

3. Pipeline 常见用途

在实际项目中,Pipeline 常用于:

  • 数据清洗
  • 去重
  • 转换格式
  • 写入 JSON 文件
  • 写入数据库

所以可以把 Item 和 Pipeline 理解为:

  • Item:定义“数据长什么样”
  • Pipeline:定义“数据怎么处理”

如果后续需要把数据写入数据库,例如 MySQL,通常也是在 Pipeline 中完成,而不是直接写在 Spider 里。

这样做的好处是:

  • Spider 只负责抓取和提取
  • Pipeline 只负责处理和保存

4. Item 与 Pipeline 小案例

下面用一个最简单的小案例,把 ItemPipeline 串起来。

假设我们要抓取一个页面标题,并把它交给 Pipeline 处理。

第一步:在 items.py 中定义数据结构

import scrapy


class TitleItem(scrapy.Item):
    title = scrapy.Field()

这段代码的作用是:

  • 定义一个 TitleItem
  • 其中只包含一个字段 title

也就是说,后续我们提取到的数据会按照这个结构来保存。


第二步:在 Spider 中提取数据并返回 Item

import scrapy
from scrapy_test.items import TitleItem


class DemoSpider(scrapy.Spider):
    name = 'demo'
    allowed_domains = ['example.com']
    start_urls = ['https://example.com']

    def parse(self, response):
        item = TitleItem()
        item['title'] = response.xpath('//title/text()').extract_first()
        yield item

这段代码的执行流程如下:

  1. 爬虫访问 https://example.com
  2. 页面下载完成后进入 parse()
  3. 创建一个 TitleItem 对象
  4. 提取页面标题并赋值给 item['title']
  5. 使用 yield item 把数据交给后续流程处理

这里最关键的一行是:

yield item

它表示:

把当前提取到的数据交给 Pipeline。


第三步:在 pipelines.py 中处理数据

class ScrapyTestPipeline:
    def process_item(self, item, spider):
        print('Pipeline 接收到的数据:', item)
        return item

process_item() 会在 Spider 提交数据后自动执行。

在这个例子中,它只是简单把数据打印出来。

但在真实项目中,这里还可以扩展为:

  • 写入 JSON 文件
  • 写入 CSV 文件
  • 写入 MySQL
  • 清洗字段内容

第四步:在 settings.py 中启用 Pipeline

ITEM_PIPELINES = {
    'scrapy_test.pipelines.ScrapyTestPipeline': 300,
}

如果没有启用这段配置,即使 pipelines.py 里写好了逻辑,Scrapy 也不会自动调用它。

因此,一个完整的数据处理链路通常是:

Spider 提取数据 → yield item → Pipeline 接收数据 → Pipeline 处理数据

通过这个小案例,可以更直观地理解:

  • Item 负责定义数据结构
  • Spider 负责提取数据
  • Pipeline 负责处理数据

十二、CrawlSpider 简介

在 Scrapy 中,除了最基础的 Spider,还有一种更适合批量跟踪链接的爬虫类型:CrawlSpider

它主要适合下面这种场景:

  • 页面之间有大量链接关系
  • 希望自动跟踪符合规则的链接
  • 希望批量抓取多个详情页

它的特点是:

  • 可以自动提取链接
  • 可以根据规则决定哪些链接跟进、哪些页面解析

通常会配合:

  • LinkExtractor
  • Rule

来使用。

其中最常见的两个对象是:

1. LinkExtractor

LinkExtractor 用于按照规则提取页面中的链接。

例如:

from scrapy.linkextractors import LinkExtractor

# 根据正则提取符合条件的链接
link1 = LinkExtractor(allow=r'list_23_\d+\.html')

# 根据 XPath 限制提取范围
link2 = LinkExtractor(restrict_xpaths='//div[@class="x"]')

# 根据 CSS 限制提取范围
link3 = LinkExtractor(restrict_css='.x')

它常见的参数有:

  • allow:允许匹配的正则规则
  • deny:不允许匹配的正则规则
  • restrict_xpaths:只在指定 XPath 范围内提取链接
  • restrict_css:只在指定 CSS 范围内提取链接

2. Rule

Rule 用来定义“提取到链接后该怎么处理”。

例如:

  • 哪些链接需要继续跟进
  • 跟进之后交给哪个解析函数处理

因此,CrawlSpider 更像是:

通过规则自动提取链接,再自动发送请求。

对于入门阶段来说,先理解它的定位即可:

普通 Spider 更适合手动控制请求流程,CrawlSpider 更适合根据规则自动跟踪链接。

所以当需求变成“从列表页不断进入详情页,再继续翻页抓取”时,CrawlSpider 往往会比普通 Spider 更省事。

3. CrawlSpider 小示例

下面给一个简化版的 CrawlSpider 示例,帮助理解它的基本写法。

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class ReadbookSpider(CrawlSpider):
    name = 'readbook'
    allowed_domains = ['www.example.com']
    start_urls = ['https://www.example.com/list_23_1.html']

    rules = (
        Rule(
            LinkExtractor(allow=r'list_23_\d+\.html'),
            follow=True
        ),
        Rule(
            LinkExtractor(allow=r'book/\d+\.html'),
            callback='parse_item'
        ),
    )

    def parse_item(self, response):
        title = response.xpath('//title/text()').extract_first()
        print(title)

这个示例中最重要的几个部分如下:

1. start_urls

start_urls 是爬虫最开始访问的入口页。

在这个例子里,它从一个列表页开始抓取。

2. 第一条 Rule

Rule(
    LinkExtractor(allow=r'list_23_\d+\.html'),
    follow=True
)

这条规则表示:

  • 提取所有符合 list_23_数字.html 这种格式的链接
  • 继续跟进这些链接
  • 但不直接调用自定义解析函数

它通常适合用来处理:

  • 列表翻页
  • 分类页翻页

3. 第二条 Rule

Rule(
    LinkExtractor(allow=r'book/\d+\.html'),
    callback='parse_item'
)

这条规则表示:

  • 提取符合详情页规则的链接
  • 访问这些详情页
  • 请求完成后交给 parse_item() 处理

这通常适合:

  • 进入详情页
  • 抓取详情页数据

4. parse_item()

def parse_item(self, response):
    title = response.xpath('//title/text()').extract_first()
    print(title)

这个函数的作用和普通 Spider 中的 parse() 类似,都是:

  • 接收响应
  • 提取数据
  • 返回结果

只不过在 CrawlSpider 中,通常是由 Rule 来决定什么时候调用它。


4. CrawlSpider 与普通 Spider 的区别

可以把它们的区别简单理解为:

普通 Spider

  • 更适合手动控制请求逻辑
  • 通常自己在 parse() 中编写 yield scrapy.Request(...)
  • 灵活度更高

CrawlSpider

  • 更适合规则比较明确的网站
  • 通过 Rule + LinkExtractor 自动跟踪链接
  • 代码往往更简洁

因此,如果你面对的是:

  • 列表页很多
  • 详情页很多
  • 链接规则比较稳定

那么 CrawlSpider 往往会更省事。


十三、简单案例说明

下面用一个简单案例,把前面的内容串起来。

假设我们要抓取一个页面的标题,可以先写一个基础 Spider:

import scrapy


class DemoSpider(scrapy.Spider):
    name = 'demo'
    allowed_domains = ['example.com']
    start_urls = ['https://example.com']

    def parse(self, response):
        title = response.xpath('//title/text()').extract_first()
        print(title)

这段代码的执行逻辑如下:

  1. 爬虫启动后访问 start_urls 中的页面
  2. 页面下载完成后,交给 parse()
  3. parse() 使用 XPath 提取标题
  4. 输出提取结果

虽然这个例子很简单,但它已经包含了 Scrapy 最核心的几个动作:

  • 发请求
  • 收响应
  • 解析内容
  • 输出结果

后续如果继续扩展,就可以进一步加入:

  • Item
  • Pipeline
  • 多页请求
  • 数据保存

因此,这个简单案例可以看作 Scrapy 爬虫项目的最小起点。

2. 导出 JSON 文件的小案例

除了直接在 parse() 中打印结果,Scrapy 还支持把抓取结果导出为文件。

下面给一个最简单的示例:抓取页面标题,并导出为 JSON 文件。

Spider 代码示例

import scrapy


class DemoSpider(scrapy.Spider):
    name = 'demo'
    allowed_domains = ['example.com']
    start_urls = ['https://example.com']

    def parse(self, response):
        title = response.xpath('//title/text()').extract_first()
        yield {
            'title': title,
            'url': response.url,
        }

这段代码和前面的基础示例很像,不同点在于:

  • 这里不再只 print(title)
  • 而是通过 yield 返回一个字典
  • 字典中的数据会被 Scrapy 当作结构化结果输出

其中:

  • title:页面标题
  • response.url:当前页面地址

运行命令示例

scrapy crawl demo -o result.json

这条命令的作用是:

  • 运行名为 demo 的爬虫
  • 把爬虫提取到的数据导出到 result.json 文件中

如果 result.json 不存在,Scrapy 会自动创建这个文件。

如果文件已经存在,通常会在原有内容后继续追加,具体行为和导出格式有关,因此实际使用时建议先检查输出文件是否需要清空。


导出结果示例

运行完成后,result.json 中可能会得到类似下面的内容:

[
  {
    "title": "Example Domain",
    "url": "https://example.com"
  }
]

这样我们就完成了一个最基础的“抓取并导出 JSON 文件”的流程。


这个案例说明了什么

通过这个小案例,可以顺便理解 Scrapy 的一个常见使用方式:

  • Spider 负责抓取页面和提取数据
  • yield 返回结构化结果
  • Scrapy 可以直接通过命令行把结果导出到文件

这对于入门非常友好,因为:

  • 不需要先写 Pipeline
  • 不需要先连接数据库
  • 先把“抓到数据”这件事跑通即可

等后续项目变复杂之后,再考虑把数据处理逻辑交给 Pipeline,会更加合适。


十四、项目开发检查清单

写 Scrapy 项目时,可以按照下面的顺序检查,避免一开始就把问题混在一起。

1. 先确认爬虫能启动

scrapy list
scrapy crawl demo

如果 scrapy list 看不到爬虫名称,优先检查:

  • 爬虫文件是否放在 spiders 目录下
  • Spider 类是否继承了 scrapy.Spider
  • name 是否写对

2. 再确认请求是否发出

parse() 中先打印响应地址:

def parse(self, response):
    print(response.url)

如果这里没有输出,说明请求可能没有进入解析方法,需要检查 start_urlsstart_requests()

3. 再确认解析表达式

不要直接在 Spider 中反复猜 XPath。建议先用 scrapy shell 测试。

scrapy shell https://example.com

进入 shell 后再验证:

response.xpath('//title/text()').get()
response.css('title::text').get()

4. 最后再处理保存逻辑

刚开始可以先用命令行导出:

scrapy crawl demo -O result.json

等字段稳定后,再考虑 Pipeline、数据库、去重等逻辑。

这个顺序很重要:

先跑通请求 -> 再验证解析 -> 再规范字段 -> 最后保存数据

不要一开始就同时写请求、解析、Pipeline、数据库,否则出错时很难判断是哪一层的问题。

十五、本篇小结

本篇我们学习了 Scrapy 最基础、最核心的内容,包括:

  • 为什么需要使用 Scrapy
  • Scrapy 是什么
  • 如何创建项目
  • 项目目录结构的作用
  • 如何创建和运行 Spider
  • Scrapy 内部的基本工作流程
  • scrapy shell 的调试方式
  • yield 的作用
  • Item 与 Pipeline 的基本定位
  • CrawlSpider 的基础概念
  • Scrapy 项目开发时的排查顺序

学完这一篇后,你应该已经能够建立一个最基本的 Scrapy 项目,并理解它是如何组织爬虫流程的。


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录