---
title: "Scrapling 检查点会保存已抓取的数据吗？"
canonical: https://wavect.io/zh/blog/scrapling-checkpoints-scraped-items/
language: zh
description: "Scrapling 检查点会保存已抓取的数据吗？通过可复现的暂停、恢复与重放实测，查看 JSON 导出覆盖、数据库写入和缺失记录核对，下载完整测试包及原始结果。"
image: "https://wavect.io/img/blog/headers/header_scrapling-checkpoints-scraped-items.png"
author: ["Kevin Riedl"]
published: "2026-11-03"
updated: "2026-11-03"
reviewed: "2026-11-03"
---

# Scrapling 检查点会保存已抓取的数据吗？

[**返回**](/zh/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/zh/team/kevin-riedl/)

[Kevin Riedl](/zh/team/kevin-riedl/) https://linkedin.com/in/wsdt

8 分钟 阅读 · 2026年11月3日 最近审核 2026年11月3日

[**下一篇**](/zh/blog/wigolo-local-web-intelligence-mcp-review/)

要点速览

Scrapling 0.5 检查点保存请求和指纹，不保存抓取记录。实测续爬后，复用 JSON 导出路径让 A 消失，SQLite 仍保留三条。重放产生重复写入，唯一键保留三行；只记错误而不重试时，写入故障仍留下缺项。应单独持久化并核对完整性。

我们的 Scrapling 爬虫保存记录 A 后暂停，恢复运行时返回了 B 和 C。再次向同一路径导出 JSON，原文件被覆盖，A 也从这份导出中消失了。

**不会。Scrapling 0.5 检查点不保存已提取的记录。**它保存待处理请求和已见请求的指纹。抓取数据需要单独持久化，使用稳定的记录标识，并在续爬后核对结果。恢复的请求队列与新一轮运行的记录列表各有职责， [检查点数据结构](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/scrapling/spiders/checkpoint.py) 明确列出了保存范围。

**实测日期：2026年11月3日。**我们使用 [10月17日发布的 Scrapling 0.5](https://github.com/D4Vinci/Scrapling/releases/tag/v0.5) ，抓取三个本地 HTTP 页面。五个独立 Python 进程分别执行连续抓取、主动暂停、恢复、手动重放检查点和注入记录写入故障。

## Scrapling 能为智能体的网页采集提供什么？

Scrapling 是一个 Python 网页抓取框架，整合 HTTP 客户端、浏览器抓取、解析器与并发爬虫。智能体可按页面是否需要渲染来选择抓取方式，提取逻辑仍使用同一套库。本次实测关注续爬后的抓取记录去了哪里。

[发布版 README](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/README.md) 列出了浏览器指纹模拟、JavaScript 渲染、重试、代理轮换、CLI 提取和 MCP 接入。项目采用 [BSD 3-Clause 许可证](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/LICENSE) 。

自适应解析可在 HTML 改动后重新定位元素。 [自适应解析指南](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/docs/parsing/adaptive.md) 说明了保存元素属性和相似度匹配的机制。重新找到元素，并不意味着提取出的记录已经持久化。更完整的检索架构可参阅我们的 [Wigolo 本地网页检索评估](/zh/blog/wigolo-local-web-intelligence-mcp-review/) 。

## Scrapling 检查点会保存抓取记录吗？

Scrapling 0.5 检查点保存待处理请求和已见请求指纹。已收集的记录列表只属于本次运行，另外使用的数据库或导出文件由应用负责。在本次固定版本的实现中， [爬虫引擎](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/scrapling/spiders/engine.py) 会在开始运行时清空记录列表。

| 存储位置 | 保存什么 | 恢复后应预期什么 |
| --- | --- | --- |
| Scrapling 检查点 | 待处理请求与已见请求指纹 | 从保存的状态继续处理剩余请求 |
| `result.items` | 本次运行保留的记录 | 不包含此前各轮运行收集的记录 |
| 应用的记录存储 | 业务代码提交到数据库等持久化位置的记录 | 是否保留取决于存储方式与写入策略 |

每轮运行后导出时，这个区别会直接影响结果。0.5 版的 `result.items.to_json(path)` 将当前列表写到指定路径。 [导出实现](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/scrapling/spiders/result.py) 会覆盖原文件，`to_jsonl(path)` 也以写入模式打开文件。两者都不会自动合并之前运行的数据。

你可以保留每轮独立的导出文件，也可以逐条写入数据库。下面的测试展示了反复使用同一导出路径的结果。

## 暂停、恢复和重放后，哪些数据还在？

Scrapling 实测中，恢复后的 SQLite 表仍有全部三条预期记录，同一路径的 JSON 导出却只剩 B 和 C。我们随后手动重放已保存的检查点，B、C 又被处理了一遍。追加日志累计五次写入，以记录标识为键的表仍只有三条记录。

测试页面通过本机回环 HTTP 提供固定的 A、B、C 三条记录。爬虫一次处理一个请求，关闭定时检查点，在 A 的数据库事务提交后暂停。每个阶段都启动新的 Python 进程。暂停、恢复与重放共用数据库和导出路径，对照组和故障组使用独立目录。

| 实测阶段 | 返回记录与 JSON 导出 | 已提交到 SQLite 的 ID | 结果 |
| --- | --- | --- | --- |
| 连续运行的对照组 | A、B、C | A、B、C | 所有预期记录均存在 |
| 提交 A 后主动暂停 | A | A | 检查点保留待处理的 B、C |
| 新进程恢复 | B、C | A、B、C | 同一路径的 JSON 导出缺少 A |
| 手动重放自己保存的检查点 | B、C | A、B、C | 追加日志中 A 一次，B、C 各两次 |
| 单独注入 B 写入故障 | A、C | A、C | `completed=True`，记录到一个回调错误，B 缺失 |

重放阶段是在恢复运行完成后，重新放回我们暂停时生成的检查点。它验证的是重复执行请求时的输出行为，没有模拟意外崩溃，也没有测量断电后能保留多少工作。

故障组的记录处理钩子在写入 B 前抛出异常，`on_error` 只记录错误，不重试。Scrapling 继续完成剩余抓取，预期记录清单的核对发现了缺项。

[下载 Scrapling 检查点测试包与实测结果](/downloads/scrapling-checkpoints-scraped-items-fixture.zip) 。其中包含本地页面、预期记录清单、工作进程与运行脚本、依赖版本、JSON 报告、追加日志和可阅读的数据库导出。

## 如何复现检查点测试？

在新的 Python 环境中安装 Scrapling 的 fetchers 扩展，再运行测试包。脚本会启动本地 HTTP 服务，依次创建五个工作进程，并独立检查导出文件与数据库记录。本实验只使用 HTTP，无需浏览器可执行文件、MCP 客户端或 AI 模型。

```
python3.12 -m venv .venv
mkdir -p .cache/pip .cache/tmp
PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_CACHE_DIR="$PWD/.cache/pip" TMPDIR="$PWD/.cache/tmp" .venv/bin/python -m pip install -r requirements-tested.txt
.venv/bin/python run_fixture.py --output results-reproduced
.venv/bin/python verify_payloads.py --results results-reproduced
```

在 Linux 上解压测试包后，进入该目录运行上述命令。实测使用 Python 3.12.14，`requirements-tested.txt` 固定了对应的依赖版本。安装前，我们核对了 [Scrapling 0.5 wheel](https://pypi.org/project/scrapling/0.5/#files) 的公开 SHA-256：

```
366f0ec9f1e7e998900e6c5e3a4063ea34062326394ced64e5c389b690572726
```

在输出目录查看 `summary.json`、`payload-validation.json` 和各阶段报告。HTTP 服务在不同工作进程之间保持运行，确保检查点中的 URL 仍然有效。每次复现都会生成自己的检查点，进程 ID、本地端口和检查点字节内容可以不同。验证会将记录标识及字段内容与预期清单比较。

## 抓取到的记录应该存在哪里？

通过 `on_scraped_item`，将 Scrapling 记录写入应用负责的持久化存储，并采用符合采集范围的记录标识。成功提交后再从钩子返回。Scrapling 会等待该钩子完成再保留记录，但写入失败仍需明确的处理策略；唯一键无法补回从未成功提交的数据。

[Spider 钩子接口](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/scrapling/spiders/spider.py) 提供了接入位置。下面是实际运行的数据库写入代码，省略了周围的观测记录逻辑：

```
self.database.execute(
    "INSERT INTO items (collection_id, item_id, payload_json) VALUES (?, ?, ?) "
    "ON CONFLICT(collection_id, item_id) DO UPDATE SET payload_json=excluded.payload_json",
    (self.manifest["collection_id"], item["id"], json.dumps(item, sort_keys=True)),
)
self.database.commit()
```

主键是 `(collection_id, item_id)`。upsert 会插入新行，或更新具有相同键的现有行。在这份固定的数据集中，A、B、C 反复写入时，各自仍对应同一行。下载包包含建表语句和完整钩子。

面对持续变化的数据，先决定新观测值应该覆盖旧值，还是保留为新版本。需要历史记录时，应将观测范围纳入标识。否则，去重可能覆盖你本来需要保留的证据。

生产集成需要可用于补处理的失败记录清单，或明确的重试策略，之后还要核对完整性。请针对实际存储端的故障验证这套策略；这个 SQLite 小型测试不能证明另一种数据库的事务恢复行为。

## 如何确认断点续爬后的数据完整？

将 Scrapling 持久化输出与计划采集的范围比较，核对预期记录标识和必需字段。本测试有独立的预期清单，所以 A 或 B 缺失时可以直接判定。真实网站需要单独确定抓取范围和发现方法，才能定义预期记录集合。请求队列处理完毕不能代替这一步。

| 验收问题 | 核对什么 | 本次实测结果 |
| --- | --- | --- |
| 是否缺少预期记录？ | 预期 ID 集合减去已存储 ID 集合 | 恢复后的 JSON 缺 A，注入写入故障后缺 B |
| 是否再次处理了同一条记录？ | 每个 ID 的产出或写入次数 | 重放序列中，B、C 各写入两次 |
| 最终存储是否按键保留一条预期记录？ | 所选采集范围内的数据库行 | 恢复和手动重放后均为三行 |
| 必需字段是否符合预期？ | 存储内容与测试清单逐项比较 | 恢复及重放后，ID、名称和来源 URL 均一致 |
| 是否还有未解决的写入错误？ | 记录处理钩子的错误与补处理记录 | 即使抓取已完成，B 的写入故障仍使验收不通过 |

[高级爬虫指南](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/docs/spiders/advanced.md) 介绍了暂停恢复、流式输出和输出钩子。用这些机制保留数据，再单独决定何时把整个数据集交给下游。

本例中，智能体或 RAG 索引若只读取恢复后导出的 JSON，就只能拿到两条记录。应从持久化存储中发布已经核对过的数据集。进程本身如何恢复是另一层问题，可参阅 [AX runner 恢复与自托管指南](/zh/blog/google-ax-agent-executor-security-self-hosting/) 。

## MCP 服务器会改变这套持久化规则吗？

Scrapling 的 MCP 服务器向兼容智能体提供网页与浏览器操作，但本实验运行的是 Python Spider API。本次检查点实测不能证明某个 MCP 工作流的持久化行为。先明确智能体将返回内容存在哪里，再针对实际需要承受的中断验证这个存储。

[v0.5 MCP 指南](https://github.com/D4Vinci/Scrapling/blob/3a8bf4e4d3ed91257ba0aa5b7dc66241d1e23840/docs/ai/mcp-server.md) 列出 16 个工具，涵盖请求会话、浏览器操作、定向提取、截图、网络检查和浏览器状态保存。登录状态与提取出的数据集仍需分别保存。

## 什么时候适合用 Scrapling 为智能体采集数据？

如果项目需要在 Python 中控制抓取、解析与爬虫行为，并且应用负责记录持久化，我们会考虑 Scrapling。先选一小批获准采集的内容，定义记录标识，执行恢复与重放，再检查存储结果。让下游依赖这份数据前，还应加入贴近实际的写入故障场景。

用有代表性的页面、必需的记录结构和重启要求，定义数据采集的验收测试。

## Scrapling 检查点常见问题

### to_jsonl 会追加之前运行的记录吗？

不会。Scrapling 0.5 以写入模式打开目标 JSONL 文件。下一轮运行仍向同一路径调用 to_jsonl，会用当前记录列表覆盖文件。你可以保留各轮独立文件，再有计划地合并；也可以在抓取过程中写入持久化存储。文件扩展名是 JSONL，不代表导出操作采用追加模式。

### 请求去重能防止数据表出现重复记录吗？

请求去重和记录标识处理的是不同问题。不同请求可能产出同一条逻辑记录，重放已保存的检查点也可能再次处理其中的待处理请求。本次受控重放中，B、C 在成功写入日志里各出现两次。采集范围与记录 ID 组成的数据库键让最终表保持三行，但没有阻止请求和写入再次执行。

### 浏览器登录状态文件会包含抓取数据吗？

不会。Scrapling 文档中的浏览器状态导出保存 Cookie、local storage 和 IndexedDB，不包含 Spider 提取的记录集合。指南还明确排除了标签页、浏览器设置与 sessionStorage。认证状态和抓取记录的存储位置应作为两项独立的应用资源处理。本测试没有执行浏览器状态保存或恢复。

### 续爬后，AutoThrottle 会保留之前学到的延迟吗？

官方爬虫指南说明，AutoThrottle 学到的延迟不写入检查点，恢复时会从配置的初始延迟开始。应在爬虫配置中保留所需的限速参数，并观察重启后的行为。这里说明的是文档和实现的范围；本次并发数为 1 的测试没有运行 AutoThrottle 自适应过程，也没有对其做性能测量。

### 这个测试能证明断电后恢复成功吗？

不能。我们使用主动暂停、新的 Python 工作进程，以及手动重放自己保存的检查点，没有在数据库提交过程中终止进程、打断存储写入或断电。结果只证明这些受控场景下的检查点、导出和带唯一键存储行为。进程突然崩溃后的数据可靠性，需要在实际存储和运行环境上单独验证。

### 预期清单能证明已经抓完网站所有页面吗？

清单只能核对它所列范围的完整性。本测试事先定义三条固定记录，缺失 ID 可以直接测量。未知网站可能还有未发现的分页、发生变化的记录或无法访问的部分。应独立确定抓取范围和发现方法，再核对该范围需要的记录。三条记录的测试通过，不能证明另一个网站已被完整抓取。

模型与基础设施

## 接下来读什么

模型选择、推理经济性、本地部署、压缩与服务架构。

[从这里开始**在欧盟自托管 LLM：开放权重模型何时才真正划算**](/zh/blog/self-hosting-llms-eu-cost/)

- [如何验证 Open Ontologies 的推导证书？](/zh/blog/open-ontologies-proof-verification/)
- [Cue 轮次检测：电话号码采集、基准测试与局限](/zh/blog/cue-turn-detection-phone-numbers/)
- [Google SAM 现名 Agent Mesh：跨机器调用 MCP 工具](/zh/blog/google-sam-agent-mesh-mcp-tools/)
- [EdgeQuake：用 PostgreSQL GraphRAG 构建 MCP 智能体记忆](/zh/blog/edgequake-postgresql-graphrag-mcp-agent-memory/)
- [BitNet CPU 推理：2B4T 的实际内存需求与 100B 说法](/zh/blog/bitnet-cpu-llm-ram-requirements/)

[上一篇文章**如何验证 Open Ontologies 的推导证书？**](/zh/blog/open-ontologies-proof-verification/) [下一篇文章**Cue 轮次检测：电话号码采集、基准测试与局限**](/zh/blog/cue-turn-detection-phone-numbers/)

[**返回**](/zh/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/zh/team/kevin-riedl/)

[Kevin Riedl](/zh/team/kevin-riedl/) https://linkedin.com/in/wsdt

8 分钟 阅读 · 2026年11月3日 最近审核 2026年11月3日

[**下一篇**](/zh/blog/wigolo-local-web-intelligence-mcp-review/)
