# https://github.com/explosion/spacy-layout 项目说明书

生成时间：2026-07-13 16:39:46 UTC

## 目录

- [项目概述、安装与快速上手](#page-1)
- [核心架构与数据流](#page-2)
- [API 参考、扩展属性与序列化](#page-3)
- [自定义、扩展与社区常见问题](#page-4)

<a id='page-1'></a>

## 项目概述、安装与快速上手

### 相关页面

相关主题：[核心架构与数据流](#page-2), [API 参考、扩展属性与序列化](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/explosion/spacy-layout/blob/main/README.md)
- [setup.py](https://github.com/explosion/spacy-layout/blob/main/setup.py)
- [pyproject.toml](https://github.com/explosion/spacy-layout/blob/main/pyproject.toml)
- [requirements.txt](https://github.com/explosion/spacy-layout/blob/main/requirements.txt)
- [spacy_layout/__init__.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/__init__.py)
- [spacy_layout/layout.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/layout.py)
- [spacy_layout/registry.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/registry.py)
- [spacy_layout/extensions.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/extensions.py)
- [examples/example_01_basic_usage.py](https://github.com/explosion/spacy-layout/blob/main/examples/example_01_basic_usage.py)
</details>

# 项目概述、安装与快速上手

## 项目概述

`spacy-layout` 是一个将 PDF / 文档版面解析结果集成进 spaCy 处理流水线的 Python 库，由 Explosion 维护。它借助 [Docling](https://github.com/DS4SD/docling) 作为底层文档解析引擎，把每一页文档中的文字、表格、图片以及对应的版面坐标转换为 spaCy 的 `Doc` / `Span` 对象，使得后续可以直接利用 spaCy 的 NLP 能力（分词、命名实体识别、关系抽取等）进行版面感知的文本分析。

主要能力包括：

- 将 PDF 转换为带有版面元数据的 `Doc` 对象，保留段落、标题、列表等结构。
- 支持表格抽取，结果以 `pandas.DataFrame` 形式暴露在 `Span._.data` 上，并可通过 `Doc._.tables` 快捷访问。
- 支持 Markdown 表示 (`Doc._.markdown`)，便于下游 LLM 直接消费。
- 保留逐元素的边界框（bounding box），便于可视化与版面分析。
- 支持 `spaCyLayout.pipe` 批量处理多份文档，接口风格与 `Language.pipe` 保持一致。

资料来源：[README.md:1-40]()
资料来源：[spacy_layout/__init__.py:1-30]()

## 安装与依赖

最简安装方式：

```bash
pip install spacy-layout
```

安装过程中会同时拉取 Docling 及其默认的 PDF 解析后端 `docling-parse`。依赖信息在 `requirements.txt` 与 `pyproject.toml` 中声明，核心运行时依赖包括 `spacy>=3.x`、`docling`、`pandas` 等。

资料来源：[setup.py:1-40]()
资料来源：[requirements.txt:1-10]()
资料来源：[pyproject.toml:1-50]()

需要特别注意的是：

- **macOS / Apple Silicon**：`spacy-layout` 在 Mac M1/M2 上的安装历史上有过依赖冲突问题（参见 issue #10），若安装失败，建议先在干净虚拟环境中升级 `pip` 与 `setuptools`，或显式安装与 Python 版本对应的 wheel。
- **CPU / GPU 选择**：底层解析可能消耗较多显存。调用前若需强制 CPU，可执行 `spacy.require_cpu()`，但部分场景下仍可能出现 CUDA OOM（参见 issue #37），建议在低显存机器上通过 `pipeline.py` 中的分批参数控制并发。
- **依赖版本冲突**：少数环境曾出现 `scipy` 与 `numpy` 的 `sph_legendre_p` ufunc 类型冲突（issue #47），可通过固定 `numpy` 版本解决。

## 快速上手

下面是一段最小可运行示例（改编自 `examples/example_01_basic_usage.py`）：

```python
import spacy
from spacy_layout import spaCyLayout

nlp = spacy.blank("en")
layout = spaCyLayout(nlp)

# 方式 1：直接传入文件路径
doc = layout("path/to/document.pdf")

# 方式 2：批量处理
docs = list(layout.pipe(["a.pdf", "b.pdf", "c.pdf"]))

print(doc.text)            # 拼装后的纯文本
print(doc._.markdown)      # Markdown 形式
print(doc._.tables)        # 文档中所有表格（DataFrame 列表）
for span in doc.spans["layout"]:
    print(span.text, span._.data)  # 段落 / 标题 / 表格等
```

整个调用流程可总结如下：

| 步骤 | 输入 | 输出 | 说明 |
|------|------|------|------|
| 1. 解析 PDF | 文件路径 / bytes / `DoclingDocument` | Docling 文档对象 | 由 Docling 完成版面与表格抽取 |
| 2. 转换为 spaCy | Docling 文档对象 | `Doc` | 在 `layout.py` 中映射为 token 与 span |
| 3. 暴露扩展属性 | `Doc` | `Doc._.markdown`、`Doc._.tables` 等 | 由 `extensions.py` 注册 |

资料来源：[examples/example_01_basic_usage.py:1-30]()
资料来源：[spacy_layout/layout.py:1-120]()
资料来源：[spacy_layout/extensions.py:1-60]()
资料来源：[spacy_layout/registry.py:1-40]()

若希望保存处理结果（issue #49 中常见的导出诉求），可借助以下模式：

```python
doc._.markdown           # 写入 .md 文件供 LLM 读取
doc._.tables.to_csv(...) # 将表格导出为 CSV
doc.to_disk("doc.spacy") # 借助 spaCy 的 DocBin 序列化（含扩展属性）
```

## 已知问题与社区反馈

根据社区高频反馈（截至 v0.0.12）：

1. **页眉 / 页脚缺失**（issue #32）：当前默认的文本拼装逻辑不会保留页眉与页脚区域，需要在源码 `layout.py` 的 `iterate_items` 阶段自行扩展过滤规则。
2. **替换解析后端**（issue #28）：可通过 `DoclingDocument` 配合自定义 backend（如 `PyPdfiumDocumentBackend`）再传入 `spaCyLayout.__call__`，自 v0.0.10 起官方已支持该输入形式。
3. **特殊字符**（issue #16）：当 PDF 使用非标准编码时，Docling 解析可能产生乱码或缺失字符，建议在解析前对源文件进行 OCR 预处理或使用替代后端。
4. **表格粒度**（issue #23）：当前仅提供表格整体边界框，不包含单元格级坐标，需要在下游任务中自行定位。
5. **跨平台安装**（issue #10）：Mac M1 平台依赖编译链路较长，推荐使用 conda 预编译包或锁版本安装。

资料来源：[spacy_layout/layout.py:120-260]()
资料来源：[spacy_layout/extensions.py:60-120]()
资料来源：[README.md:40-120]()

通过上述步骤即可在 10 分钟内完成 `spacy-layout` 的安装与首份 PDF 的版面抽取，并将其接入既有 spaCy 流水线进行进一步分析。

---

<a id='page-2'></a>

## 核心架构与数据流

### 相关页面

相关主题：[项目概述、安装与快速上手](#page-1), [API 参考、扩展属性与序列化](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [spacy_layout/layout.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/layout.py)
- [spacy_layout/types.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/types.py)
- [spacy_layout/util.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/util.py)
- [spacy_layout/__init__.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/__init__.py)
- [spacy_layout/span.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/span.py)
- [spacy_layout/token.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/token.py)
</details>

# 核心架构与数据流

## 项目定位与核心目标

`spacy-layout` 是一个将 **PDF/扫描文档** 解析为 **spaCy `Doc` 对象** 的桥接库，其核心思想是把 [Docling](https://github.com/DS4SD/docling) 的版面分析结果（`DoclingDocument`）映射为 spaCy 原生的 `Token`、`Span`、`SpanGroup`、`Doc` 层级结构，从而把版面信息（页眉、页脚、段落、表格、图像、阅读顺序）和布局坐标（bbox）暴露在熟悉的 spaCy API 中 资料来源：[spacy_layout/layout.py:1-40]()。

库对外只暴露一个核心类 `spaCyLayout`，它继承自 `spacy.Language.factory` 注册的工厂组件，可以像普通 pipeline 组件一样被 `add_pipe` 接入到任意 `Language` 中，例如 `spacy.blank("en")` 资料来源：[spacy_layout/layout.py:42-70]()。

## 整体架构与组件

整体由三层构成：**输入解析层（Docling）→ 版面映射层（spaCyLayout）→ spaCy 原生对象层（Doc/Span/Token）**。三者之间的关系如下表所示：

| 层级 | 关键类/函数 | 职责 |
|------|----------|------|
| 输入解析层 | `docling.document_converter.DocumentConverter` | 将 PDF/图片字节转换为 `DoclingDocument` |
| 版面映射层 | `spaCyLayout.__call__` / `.pipe` / `.process` | 遍历版面节点，调分词、坐标、表格展开 |
| spaCy 原生对象层 | `Doc`、`Span._.layout`、自定义 `Token` 扩展 | 承载文本、bbox、`x`、`y`、`width`、`height` 等属性 |

`spaCyLayout` 在初始化时通过 `Language.factory` 注册名为 `"spacy_layout"` 的工厂，并附带默认配置（`overlap_filter`, `extra_info`, `display_table`, `docling_backend`）资料来源：[spacy_layout/layout.py:42-90]()。`__init__` 会调用 `util.get_docling converter` 惰性构建 `DocumentConverter`，因此未传入 `.pdf` 时不会真正加载 Docling，导入更轻量 资料来源：[spacy_layout/util.py:1-40]()。

## 数据流：从文档到 spaCy Doc

处理一个文档的典型数据流如下：

1. **接收输入**：用户调用 `layout("file.pdf")` 或传入 `bytes`，构造函数内部统一交给 `DocumentConverter.convert_single` 解析；若已是 `DoclingDocument`（v0.0.10+）则直接复用 资料来源：[spacy_layout/layout.py:103-130]()。
2. **遍历版面节点**：`process` 调用 `util.iter_paragraphs(doc)` 或 `_iter_paragraphs_keep_headers` 递归遍历 Docling 的文档树，过滤掉误识别的小框，过滤策略由 `overlap_filter` 控制 资料来源：[spacy_layout/util.py:42-90]()。
3. **文本归一化与坐标**：对每个 `text` 节点，使用 `normalize_bbox` 把 Docling 的坐标系（左下/左上原点均可）映射为 `page_no`、`x`、`y`、`width`、`height`，并附带单元格的列/行索引 资料来源：[spacy_layout/util.py:92-160]()。
4. **构造 `Doc`**：把全部文本段落拼接成 `full_text`，使用 `nlp.tokenizer(full_text)` 拿到一个空但已分词的 `spacy.tokens.Doc`，再在 pipeline 中由 `spaCyLayout.__call__` 把段落回填为 `SpanGroup("layout")` 资料来源：[spacy_layout/layout.py:132-200]()。
5. **挂载扩展属性**：`Doc._.layout`（整个版面分组）、`Span._.data`（表格的 `pandas.DataFrame`）、`Doc._.tables`、`Doc._.markdown`、`Doc._.page_size`、`Span._.page_no` 等通过 `spacy_layout.token` 注册的 `Token`/`Span`/`Doc` 扩展被填充 资料来源：[spacy_layout/token.py:1-40]()、`[spacy_layout/span.py:1-40]()`。

`as_tuples` 参数（v0.0.12 引入）使 `pipe` 与 spaCy 原生 `Language.pipe` 行为对齐，可处理 `(context, doc_bytes)` 元组 资料来源：[spacy_layout/layout.py:200-260]()。

## 关键设计点与已知限制

- **页眉页脚丢失**：默认 `_iter_paragraphs` 仅跟踪 `iterate_items`，未将 Header/Footer 节点纳入 `text` 列表，社区反馈后可通过自定义迭代器修复（参见 issue #32）资料来源：[spacy_layout/util.py:42-90]()。
- **后端可替换**：`DocumentConverter` 接受 `format_options={"pdf_backend": ...}`，因此可切换为 `PyPdfiumDocumentBackend` 或 `DoclingParseV2DocumentBackend`（参见 issue #28）资料来源：[spacy_layout/util.py:1-40]()。
- **CPU/GPU 控制**：`layout` 流程中调用 Docling 不会读取 `spacy.require_cpu()`，需要用户预先设置 `CUDA_VISIBLE_DEVICES` 等环境变量（参见 issue #37）资料来源：[spacy_layout/layout.py:103-130]()。
- **表格 API**：`Span._.data` 返回 `pandas.DataFrame`；`display_table` 回调可定制 `Doc.text` 中表格的呈现方式；`Doc._.markdown` 提供文档的 Markdown 字符串（自 v0.0.9 起）资料来源：[spacy_layout/types.py:1-60]()。
- **序列化**：`Doc`/`Doc._.tables`/`Doc._.markdown` 等扩展属性随 `DocBin` 持久化，需在反序列化端同样 `import spacy_layout` 以注册扩展（参见 v0.0.8 release notes）资料来源：[spacy_layout/__init__.py:1-20]()。

整套设计的精妙之处在于：**Docling 负责"看"文档，spaCy 负责"读"文档**，库本身只做一层薄薄的语义映射，使版面信息天然兼容现有的 spaCy 生态（训练、可视化、Matchers、Pipeline 组件）。

---

<a id='page-3'></a>

## API 参考、扩展属性与序列化

### 相关页面

相关主题：[核心架构与数据流](#page-2), [自定义、扩展与社区常见问题](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [spacy_layout/layout.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/layout.py)
- [spacy_layout/types.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/types.py)
- [spacy_layout/__init__.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/__init__.py)
- [spacy_layout/tests/test_serialize.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/tests/test_serialize.py)
- [README.md](https://github.com/explosion/spacy-layout/blob/main/README.md)
- [pyproject.toml](https://github.com/explosion/spacy-layout/blob/main/pyproject.toml)
</details>

# API 参考、扩展属性与序列化

## spaCyLayout 主类与工厂接口

`spaCyLayout` 是 spacy-layout 提供的 spaCy 工厂组件，遵循 spaCy 的 `Language.factory` 注册约定。`spaCyLayout(nlp)` 会返回一个可注册到流水线上的组件实例，调用方式支持单文档与批量两种。

单文档入口 `__call__` 既可接受文件路径（`str` / `Path`）或 `bytes`，也可接受已由 Docling 处理好的 `DoclingDocument`（自 v0.0.10 起支持）。`资料来源：[spacy_layout/layout.py:1-80]()`

批量入口 `pipe` 在底层使用 `nlp.pipe` 完成分词，并对输入流进行惰性求值。v0.0.12 引入了 `as_tuples` 参数，行为与 `Language.pipe` 一致，便于把 `(context, doc)` 形式的元组透传到流水线下游。`资料来源：[spacy_layout/layout.py:80-140]()`

## 自定义扩展属性

spacy-layout 通过 spaCy 的 `set_extension` 机制挂载自定义属性，使得 `Doc` 与 `Span` 在不破坏原有 API 的前提下携带布局信息。

### Doc 级扩展

| 属性 | 类型 | 含义 |
| --- | --- | --- |
| `Doc._.layout` | `List[LayoutSpan]` | 整篇文档的布局段集合，按阅读顺序排列 |
| `Doc._.pages` | `List[PageInfo]` | 每一页的元信息，包括尺寸、页码与边界框 |
| `Doc._.tables` | `List[Span]` | 快捷访问，指向所有被识别为表格的 span |
| `Doc._.markdown` | `str` | 整篇文档的 Markdown 表示（v0.0.9 引入） |

`资料来源：[spacy_layout/types.py:1-60]()`

### Span 级扩展

- `Span._.layout` / `Span._.data`：`LayoutSpan` 携带的原始 `DoclingDocument` 节点引用与可选的 `pandas.DataFrame`（v0.0.6 起用于表格数据）。
- `Span._.x` / `Span._.y` / `Span._.width` / `Span._.height`：覆盖 spaCy 标准的 bbox 扩展，强制以"左下原点"或"左上原点"坐标给出（v0.0.4 / v0.0.7 修复）。
- `资料来源：[spacy_layout/types.py:60-120]()`

> 社区反馈（issue #32）指出页眉与页脚默认被排除在 `Doc._.layout` 之外；如需保留，应在 Docling 的预处理阶段对页面布局策略进行调整。`资料来源：[spacy_layout/layout.py:140-200]()`

## 数据结构与边界框约定

`LayoutSpan`、`PageInfo` 等数据结构集中在 `types.py` 中定义。布局跨度包含以下关键字段：

1. `page`：所属页码（自 v0.0.11 修正了页码回归问题）。
2. `label`：布局类型（`title` / `text` / `table` / `list` 等）。
3. `bbox` / `x` / `y` / `width` / `height`：坐标以 Docling 给出的 PDF 用户空间为准。
4. `span`：在 `Doc` 中对应的字符级 `Span`。
5. `data`：可选 `pandas.DataFrame`，仅在 `label == "table"` 时填充。

`资料来源：[spacy_layout/types.py:1-60]()`

`spaCyLayout` 还支持通过 `display_table` 回调自定义表格在 `Doc.text` 中的呈现方式，便于把表格序列化为占位符或简化的 Markdown。`资料来源：[spacy_layout/layout.py:200-260]()`

## 序列化：DocBin 与扩展属性

将包含布局信息的 `Doc` 写入 `DocBin` 时，必须确保自定义扩展属性的序列化器被正确注册。v0.0.8 修复了 `pandas.DataFrame` 与扩展属性经 `DocBin` 存取后类型丢失的问题。`资料来源：[spacy_layout/tests/test_serialize.py:1-60]()`

典型用法：

```python
import spacy
from spacy_layout import spaCyLayout
from spacy.tokens import DocBin

nlp = spacy.blank("en")
nlp.add_pipe("spacy_layout")
doc = nlp("report.pdf")

doc_bin = DocBin(store_user_data=True)
doc_bin.add(doc)
doc_bin.to_disk("./docs.spacy")

# 还原
reloaded = list(DocBin().from_disk("./docs.spacy").get_docs(nlp.vocab))[0]
assert reloaded._.pages == doc._.pages
```

> 使用建议：`store_user_data=True` 是保留 `_.layout` 等扩展属性的关键；`spacy serialize` CLI 在传入 `--store-user-data` 时同样生效。`资料来源：[spacy_layout/layout.py:260-320]()`

## 安装与依赖关系

`pyproject.toml` 中将 `spacy` 与 `docling` 声明为核心依赖，并可选暴露 `pandas`。在 macOS（M1/M2）上若遇到 `pip install` 失败（issue #10），建议使用与本机 Python 版本一致的虚拟环境，并升级 `pip` 与 `setuptools` 后重试。`资料来源：[pyproject.toml:1-40]()`

## 导出与下游消费

- 文本/Markdown 导出：直接使用 `doc.text` 或 `doc._.markdown`。
- CSV/JSON 导出：遍历 `doc._.layout`，将每条 `LayoutSpan` 序列化为字典后使用 `pandas.DataFrame` 或 `json` 写出。
- 自定义下游解析：可传入 `DoclingDocument` 至 `__call__` 复用上游 OCR/解析结果（v0.0.10）。
- `资料来源：[README.md:1-120]()`

## 常见误区与限制

1. `spacy.require_cpu()` 不会自动影响 Docling 的运行设备，OOM 时需要显式在 Docling 配置中切换后端（issue #37）。
2. 表格只提供整体 bbox，不含单元格级别坐标（issue #23）；如需粒度更细的数据，应直接消费 `Span._.data` 中的 `DataFrame`。
3. 特殊字符（变音符号、`ª`、`º` 等）需保证 PDF 字体可被 Docling 正确解码（issue #16）。
4. 默认后端为 `docling-parse`，如需切换为 `PyPdfiumDocumentBackend` 需通过 Docling 的 `DocumentConverter` 注入（issue #28）。`资料来源：[spacy_layout/layout.py:320-360]()`

---

<a id='page-4'></a>

## 自定义、扩展与社区常见问题

### 相关页面

相关主题：[核心架构与数据流](#page-2), [API 参考、扩展属性与序列化](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [spacy_layout/layout.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/layout.py)
- [spacy_layout/util.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/util.py)
- [spacy_layout/__init__.py](https://github.com/explosion/spacy-layout/blob/main/spacy_layout/__init__.py)
- [README.md](https://github.com/explosion/spacy-layout/blob/main/README.md)
- [setup.py](https://github.com/explosion/spacy-layout/blob/main/setup.py)
- [pyproject.toml](https://github.com/explosion/spacy-layout/blob/main/pyproject.toml)
</details>

# 自定义、扩展与社区常见问题

本页聚焦 spaCy-layout 的扩展机制（回调、后端切换、Docling 直通）和真实用户常见问题（导出、字符编码、表格/页眉页脚、性能、替代方案），帮助开发者定位问题与扩展点。

## 扩展点与自定义能力

### 1. 表格文本显示回调：`display_table`

`Doc.text` 在遇到表格时默认会渲染为某种文本表示。`spaCyLayout.__call__` 接受 `display_table` 关键字参数，允许用户传入可调用对象来自定义表格如何出现在 `Doc.text` 中。这是从 v0.0.6 起的官方扩展点。资料来源：[spacy_layout/layout.py:1-50]() / [README.md:1-80]()

### 2. 切换 PDF 解析后端

默认情况下 `DocumentConverter` 使用 `docling-parse`。如果希望换成 `PyPdfiumDocumentBackend`（或自定义后端），需要自行构造 `DocumentConverter(...)` 后传入 `spaCyLayout`。构造函数本身并未暴露 `converter` 参数，但用户可以先调用底层 Docling 流程获得 `DoclingDocument`，再把它作为输入直接送入 `__call__`（见下）。资料来源：[spacy_layout/layout.py:50-120]()

### 3. 直接传入 `DoclingDocument`

从 v0.0.10 起，`spaCyLayout.__call__` 接受已经处理过的 `DoclingDocument`，跳过重新解析阶段。这有两个价值：①复用已有中间产物，避免重复解析大文件；②让用户能嵌入自己的 Docling 流程（例如 Azure 替代解析后的对象）。资料来源：[README.md:80-160]()

### 4. 访问 Docling 内部特性

当前 `spaCyLayout` 主要抽取 layout（位置 + 文本）层信息，并不把 `DoclingDocument` 上的图像列表、picture 分类、figure 等结构透出。用户如需这些特性，应在传入 `spaCyLayout` 之前使用 `DoclingDocument` 的 API（例如 `doc.pictures`），或在闭 issue #40 中追踪官方进展。资料来源：[spacy_layout/layout.py:120-200]()

## 数据导出与序列化

`Doc` 提供了三个常用导出抓手：

| 导出目标 | API | 适用场景 |
| --- | --- | --- |
| 纯文本 | `Doc.text` | 终端查看、给 LLM 阅读 |
| Markdown | `Doc._.markdown`（v0.0.9 引入） | 保留表格/层级结构 |
| 表格 DataFrame | `Span._.data`（v0.0.6 引入） | 后续 pandas/CSV 处理 |

要落盘为文件，可直接写入 IO，例如：

```python
with open("out.md", "w", encoding="utf-8") as f:
    f.write(doc._.markdown)
```

如果使用 `nlp.pipe` 批量处理多份 PDF，可借助 `DocBin` 序列化（v0.0.8 起已修正扩展属性和 `pandas.DataFrame` 的序列化问题）。资料来源：[spacy_layout/layout.py:200-280]() / [README.md:160-240]()

## 社区常见问题与规避

### 特殊字符（葡萄牙语等）乱码

部分 PDF 文本在源文档层面就缺失变音符号。spaCy-layout 不做字符修复；遇到 `jurisprudência` 被切成 `jurisprudncia` 时，应检查源 PDF 的字体嵌入，或在 Docling 层加入字符映射 hook。资料来源：[issue #16]() / [spacy_layout/util.py:1-60]()

### 表格单元格的精细 bbox

`Span`（表格）的 `_.x` / `_.y` 等位置属性只覆盖整张表的包围盒；单元格级别坐标需直接操作 `DoclingDocument` 中的 `TableItem`。issue #23 中维护者已确认这属于"待办"。资料来源：[spacy_layout/layout.py:280-340]() / [issue #23]()

### 页眉页脚缺失

`layout.py` 在遍历 `document.iterate_items()` 时只取主文本节点，page-header / page-footer 类型会被排除。若需包含，可在 fork 版本中扩展节点类型白名单。资料来源：[spacy_layout/layout.py:120-200]() / [issue #32]()

### 性能、CPU 与依赖兼容性

- 安装在 macOS（M1）上偶发失败，多与 `docling` / `pytorch` 的 wheel 兼容性相关，参考 spaCy issue #5120 中的 `pip install --no-deps` 分步安装思路。资料来源：[issue #10]()
- 即使调用了 `spacy.require_cpu()`，底层的 Docling/PyTorch 仍可能默认尝试 GPU；应在运行前显式设置 `CUDA_VISIBLE_DEVICES=""` 或在导入 docling 前 `torch.set_default_device("cpu")`。资料来源：[issue #37]()
- `sph_legendre_p` 报错（`ValueError: Incompatible ufunc type ...`）是 scipy 与 numpy ABI 不匹配导致，需重新对齐两者的版本，或在干净虚拟环境中安装 spaCy-layout。资料来源：[issue #47]() / [setup.py:1-40]()

### 替代 Docling 的 PDF 解析方案

由于 spaCy-layout 仅依赖 `DoclingDocument` 这一中间表示，理论上可以接 Azure Document Intelligence、Unstructured、Marker 等输出结构化文档的工具——只要把它们的输出转换为 `DoclingDocument` 即可。issue #41 中维护者建议先研究 `DocumentConverter` 的导出语义。资料来源：[spacy_layout/layout.py:50-120]() / [issue #41]()

### 一次处理多文件：`pipe` 与 `as_tuples`

v0.0.12 起 `spaCyLayout.pipe` 添加了 `as_tuples` 参数，与 `Language.pipe` 行为一致，可与 `(text, context)` 形式配合，便于大批量 PDF 导入流水线。资料来源：[spacy_layout/layout.py:340-420]() / [pyproject.toml:1-40]()

## 小结

spaCy-layout 的扩展面集中在三个位置：`display_table` 回调（文本渲染）、`DoclingDocument` 直通输入（复用与替换后端）、`Span._.data` / `Doc._.markdown`（结构化导出）。对于"页眉页脚、单元格 bbox、字符修复"等高频诉求，目前需在 fork 或上游 issue 中实现，库本身以"薄封装"为定位，避免过度承诺。

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：explosion/spacy-layout

摘要：发现 12 个潜在踩坑项，其中 3 个为 high/blocking；最高优先级：安装坑 - 来源证据：How to use alternate PDF parser backend?。

## 1. 安装坑 · 来源证据：How to use alternate PDF parser backend?

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：How to use alternate PDF parser backend?
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/28 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 安装坑 · 来源证据：Not able to install spacy-layout in MacOS

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Not able to install spacy-layout in MacOS
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/10 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 3. 安装坑 · 来源证据：layout() does not seem to respect spacy.require_cpu()

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：layout() does not seem to respect spacy.require_cpu()
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/37 | 来源类型 github_issue 暴露的待验证使用条件。

## 4. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/explosion/spacy-layout | README/documentation is current enough for a first validation pass.

## 5. 维护坑 · 来源证据：ValueError: Incompatible ufunc type between scipy and numpy in sph_legendre_p

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个维护/版本相关的待验证问题：ValueError: Incompatible ufunc type between scipy and numpy in sph_legendre_p
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/47 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 6. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/explosion/spacy-layout | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/explosion/spacy-layout | no_demo; severity=medium

## 8. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/explosion/spacy-layout | no_demo; severity=medium

## 9. 安全/权限坑 · 来源证据：Accessing Docling features from within Spacy Layout

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Accessing Docling features from within Spacy Layout
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/40 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 10. 安全/权限坑 · 来源证据：How to export as a file

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：How to export as a file
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/explosion/spacy-layout/issues/49 | 来源类型 github_issue 暴露的待验证使用条件。

## 11. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/explosion/spacy-layout | issue_or_pr_quality=unknown

## 12. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/explosion/spacy-layout | release_recency=unknown

<!-- canonical_name: explosion/spacy-layout; human_manual_source: deepwiki_human_wiki -->
