一、为什么要学习 Scrapy
在前面的章节中,我们已经学习了如何使用 urllib、requests 发送请求,也学习了如何通过 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 是否安装到了当前正在使用的解释器中
- 环境变量是否配置正确
在实际使用中,建议优先确认两件事:
pip install scrapy是否执行成功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:起始 URLparse():解析函数
下面分别说明。
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 会自动完成下面这些步骤:
- 找到对应名称的爬虫
- 读取项目配置
- 发送起始请求
- 获取响应内容
- 调用
parse()函数解析数据 - 处理提取结果
也就是说,运行 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
或者更直白一点:
- Spider 提供初始请求
- 调度器管理请求
- 下载器发送请求并下载页面
- Spider 解析页面
- 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 获取到的通常是 Selector 或 SelectorList 对象,它们还可以继续调用:
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 itemyield 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 小案例
下面用一个最简单的小案例,把 Item 和 Pipeline 串起来。
假设我们要抓取一个页面标题,并把它交给 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
这段代码的执行流程如下:
- 爬虫访问
https://example.com - 页面下载完成后进入
parse() - 创建一个
TitleItem对象 - 提取页面标题并赋值给
item['title'] - 使用
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。
它主要适合下面这种场景:
- 页面之间有大量链接关系
- 希望自动跟踪符合规则的链接
- 希望批量抓取多个详情页
它的特点是:
- 可以自动提取链接
- 可以根据规则决定哪些链接跟进、哪些页面解析
通常会配合:
LinkExtractorRule
来使用。
其中最常见的两个对象是:
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)
这段代码的执行逻辑如下:
- 爬虫启动后访问
start_urls中的页面 - 页面下载完成后,交给
parse() parse()使用 XPath 提取标题- 输出提取结果
虽然这个例子很简单,但它已经包含了 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_urls 或 start_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 项目,并理解它是如何组织爬虫流程的。