Skip to content
LiteParse 文档版本 跟随上游 源快照 4bf66c1f 更新于 2026-10-16

LiteParse —— 开源 PDF 解析器,支持空间文字抽取、OCR 与边界框。

本 crate 是核心 Rust 库。Node.js、Python 与 WebAssembly 的语言绑定以符合各语言习惯的封装,重新导出了同一批类型。

[LiteParse::parse] 运行的是一条固定流水线;[stages] 模块把其中每一步都作为公开函数暴露出来,供需要自己编排流水线的调用方使用。

结构体 LiteParseConfig

LiteParse 文档解析的配置。

pub struct LiteParseConfig {
    pub ocr_language: String,
    pub ocr_enabled: bool,
    pub ocr_server_url: Option<String>,
    pub ocr_server_headers: Vec<(String, String)>,
    pub tessdata_path: Option<String>,
    pub max_pages: usize,
    pub target_pages: Option<String>,
    pub extract_screenshots: bool,
    pub continue_on_page_error: bool,
    pub dpi: f32,
    pub output_format: OutputFormat,
    pub preserve_very_small_text: bool,
    pub password: Option<String>,
    pub quiet: bool,
    pub num_workers: usize,
    pub image_mode: ImageMode,
    pub extract_images: bool,
    pub image_output_dir: Option<String>,
    pub extract_links: bool,
    pub keep_headers_footers: bool,
    pub extract_annotations: bool,
    pub extract_form_fields: bool,
    pub extract_structure_tree: bool,
    pub extract_blocks: bool,
    pub extract_content_bounds: bool,
    pub extract_xfa_packets: bool,
    pub extract_document_metadata: bool,
    pub detect_screenshot_rects: bool,
    pub render_form_fields: bool,
    pub ocr_failure_fatal: bool,
    pub ocr_hedge_delays_ms: Vec<u64>,
    pub emit_word_boxes: bool,
    pub extract_text_metadata: bool,
    pub crop_box: Option<CropBox>,
    pub skip_diagonal_text: bool,
    pub page_orientation_corrections: Vec<PageOrientationCorrection>,
    pub include_complexity: bool,
    pub extract_vector_graphics: bool,
}

字段

名称类型文档
ocr_languageStringOCR 语言代码(Tesseract 格式:“eng”、“fra”、“deu” 等)。
ocr_enabledbool是否启用 OCR。为 true 时,对文字稀疏页与内嵌图片执行 OCR。
ocr_server_urlOption<String>HTTP OCR 服务 URL(未提供时使用 Tesseract)
ocr_server_headersVec<(String, String)>每次请求 ocr_server_url 时附带的额外 HTTP 头,形如 (name, value) 键值对。用于鉴权,例如 ("Authorization", "Bearer …")。ocr_server_url 为 None 时忽略。
tessdata_pathOption<String>tessdata 目录路径。未设置时回退到 TESSDATA_PREFIX 环境变量。
max_pagesusize最多解析多少页。
target_pagesOption<String>指定要解析的页(例如 “1-5,10,15-20”)。为 None 表示全部页。
extract_screenshotsbool把解析出的页面渲染为 PNG 并通过 ParseResult.screenshots 返回。默认 false;PNG 载荷可能很大。
continue_on_page_errorbool在某页发生 PDFium 抽取失败后继续解析,并在 ParseResult.page_errors 中报告。默认 false 以保留快速失败行为。无论该项如何设置,打开文档与文档级失败仍然是致命的。
dpif32渲染页面的 DPI(供 OCR 与截图使用)。
output_formatOutputFormat输出格式。
preserve_very_small_textbool保留通常会被过滤掉的极小文字。
passwordOption<String>加密/受保护文档的密码。
quietbool抑制进度输出。
num_workersusize并发 OCR 工作线程数。默认为(CPU 核数 - 1),最小 1。
image_modeImageMode控制位图引用在 markdown 输出里如何呈现。该项不会开启内嵌图片抽取。
extract_imagesbool把内嵌图片的字节与元数据抽取到 ParseResult.images。默认 false。为向后兼容,ImageMode::Embed 也会开启抽取(见 [LiteParseConfig::effective_extract_images])。
image_output_dirOption<String>抽取出的内嵌图片写到的目录。要求 extract_images 为 true。
extract_linksbool抽取超链接批注,并在 markdown 输出里渲染成 [text](url)。默认开启。做基准对比(纯文本 ground truth 从不使用链接语法)时可关闭。
keep_headers_footersbool在 markdown 输出里保留滚动的页眉/页脚,而不是剥离。默认情况下,markdown 渲染器会移除在多篇页面的上/下页面带里重复出现的行(以及 Page N of M 这类单页版式)。设为 true 即全部保留 —— 对宁可在下游去重、也不愿丢内容的抽取流程很有用。只影响 Markdown 输出。
extract_annotationsbool把所有 PDF 批注抽取进每个解析出的页面。默认 false。这与 extract_links 相互独立,后者只控制 Markdown 的链接重建。
extract_form_fieldsbool抽取 AcroForm 控件字段与值。默认 false。
extract_structure_treebool抽取标签 PDF 的逻辑结构树。默认 false。
extract_blocksbool输出每页分类好的版面块(标题、段落、列表项、带逐格边界框的表格、代码、分隔线、图形)及其边界框。默认 false。这就是 Markdown 渲染器所消费的同一套拆解结果,只是以数据形式暴露。它与 output_format 无关:blocks 在 JSON 与 text 模式下同样可得,开启它也绝不会改变渲染出的 Markdown。
extract_content_boundsbool输出每页的 content_bounds:其顶层内容对象在视口坐标下的边界框并集(可见内容的范围)。默认 false,以保持默认输出形态不变。只要开启 extract_vector_graphics,内容边界仍会内部计算以供白填充启发式使用。
extract_xfa_packetsbool从 XFA 表单文档中抽取原始 XFA 数据包(名称 + XML 内容)到 ParseResult.xfa_packets。默认 false。非 XFA 文档返回空列表。
extract_document_metadatabool把文档级来源元数据收集到 ParseResult.doc_meta。默认 false:对由非 PDF 格式转换而来的输入为 None,因为这些事实描述的是中间 PDF 而非调用方的文件。
detect_screenshot_rectsbool在渲染出的页面截图里检测实心矩形与粗线,并挂到每个 ScreenshotResult.rects 上。它工作在位图上,因此也能在没有矢量路径的扫描/压平页里找到结构。默认 false(每页多一次全位图扫描)。
render_form_fieldsbool把 AcroForm 字段外观(已填值、复选框状态)画进渲染出的位图(截图与 OCR 输入)。这会初始化一个 PDFium 表单填充环境并执行文档的 open/JS 动作,因此默认关闭:普通解析既不该执行文档脚本,也不该改变带表单 PDF 的位图字节。
ocr_failure_fatalbool系统性的 OCR 失败(所有 OCR 任务都失败,且至少一个是主要文字来源为 OCR 的文字稀疏页)是否让整个解析中止。默认 true:暴露根因,而不是静默输出空白页。设为 false 时,OCR 不可用会保留已恢复的原生文字并返回部分结果 —— 适合宁可要降级文档也不要硬失败的调用方(例如宿主本身有 OCR 兜底,或把 OCR 当作尽力而为的增强)。
ocr_hedge_delays_msVec<u64>针对 HTTP OCR 引擎的请求对冲时间表(毫秒)。为空(默认)表示不对冲。给出多个延时(例如 [0, 5000, 10000, 15000, 20000])时,每次 OCR 尝试都会在每个延时各发一个重复请求,并取最先成功的那个 —— 用额外的 OCR 服务负载换取慢速/卡死 pod 上更低的尾部延迟。对 Tesseract 引擎无影响。
emit_word_boxesbool在每个 TextItem 上输出逐词子框(TextItem.words)。默认 false:文字项本身已带自己的框,而逐词框会让文字项载荷大约翻倍(体积 + napi 序列化),所以只对做词级边界框归属的调用方才值得计算。为 false 时 TextItem.words 恒为空,逐词追踪完全跳过(零分配)。
extract_text_metadatabool在公开的文字项上附带丰富的 PDF 文字元数据:MCID、字形宽度、字体度量/字重/异常状态、填充/描边颜色、原始字符码以及生成的尾随空格状态。默认 false,以保持 LiteParse 轻量的响应形态。版面所需的度量在内部依然可得;源字符码与生成空格状态只有开启该项才会计算。
crop_boxOption<CropBox>把输出限制在每页的某个子区域。每个字段表示从对应边裁掉的页面比例(例如 left = 0.5 丢弃左半边)。只有当文字项完全落在保留矩形 [left·W, (1-right)·W] × [top·H, (1-bottom)·H](左上原点)之内时才保留。None(默认)保留整页。它在 OCR 合并之后应用,因此区域之外的 OCR 文字也会被丢弃。
skip_diagonal_textbool丢弃倾斜文字 —— 旋转角度与最近直角(0/90/180/270)偏离超过 2° 的项。默认 false。
page_orientation_correctionsVec<PageOrientationCorrection>由调用方提供的逐页朝向修正,例如来自一个看过渲染页面的上游朝向分类器。每条记录指明一个从 1 开始的页号,以及该页内容在视口中呈现出的顺时针旋转角(0/90/180/270);LiteParse 会在抽取前按该角度反向旋转该页,于是文字坐标、阅读顺序、页面尺寸与 OCR 位图都会正向输出。它在 PDF 自身的 /Rotate 之上叠加。未列出的页以及超出文档末尾的页保持原样。默认为空。
include_complexitybool在 parse 期间计算逐页复杂度信号,并挂到每个 ParsedPage 上(在 JSON 里以每页一个 complexity 对象呈现)。这些信号与独立的 is_complex API 返回的完全相同。默认 false。
extract_vector_graphicsbool在解析结果里暴露页面级的矢量路径数据(shapes 与合并后的水平/垂直 lines)。默认 false;即使关闭,路径对象仍会在内部被版面检测查看。

方法

  • pub fn effective_extract_images(self: &Self) -> bool { /* ... */ }

    是否应当执行内嵌图片抽取。为 true 的条件是

  • pub fn effective_emit_word_boxes(self: &Self) -> bool { /* ... */ }

    本次运行是否需要逐词框,无论由哪个阶段

  • pub fn output_word_boxes(self: &Self) -> bool { /* ... */ }

    绑定层是否返回 TextItem.words(napi、python、wasm;

结构体 PageOrientationCorrection

调用方为某一页提供的朝向修正。见 [LiteParseConfig::page_orientation_corrections]。

pub struct PageOrientationCorrection {
    pub page: u32,
    pub angle: u16,
}

字段

名称类型文档
pageu32从 1 开始的文档页号。
angleu16该页内容在视口中呈现出的顺时针角度;必须是 0、90、180、270 之一。

方法

  • pub fn quarter_turns_to_apply(self: &Self) -> Result<i32, String> { /* ... */ }

    需要加到页面 /Rotate 上的四分之一圈数,使内容读起来

结构体 CropBox

以「每边裁掉的比例」表示的页面子区域。所有字段取值都在 [0, 1];区域非空要求 left + right < 1 且 top + bottom < 1。原点在左上角,与 TextItem 坐标一致。

pub struct CropBox {
    pub top: f32,
    pub right: f32,
    pub bottom: f32,
    pub left: f32,
}

字段

名称类型文档
topf32
rightf32
bottomf32
leftf32

枚举 ImageMode

属性:

  • Other("#[serde(rename_all = \"lowercase\")]")

markdown 输出器使用的图片处理方式。

  • Off —— 完全不输出图片引用。
  • Placeholder(默认)—— 按阅读顺序,在每个图片的 y 位置输出 ![](img_pN_K.png) 引用,但不抽取也不返回像素字节。既让响应体积保持小,又让 LLM 能看到图表在文档里的位置。
  • Embed —— 输出与 Placeholder 相同的引用,并把内嵌像素字节抽取到 ParseResult.images(等价于设置 LiteParseConfig::extract_images)。
pub enum ImageMode {
    Off,
    Placeholder,
    Embed,
}

枚举变体

Off

Placeholder

Embed

枚举 OutputFormat

属性:

  • Other("#[serde(rename_all = \"lowercase\")]")

支持的输出格式。

pub enum OutputFormat {
    Json,
    Text,
    Markdown,
}

枚举变体

Json

Text

Markdown

常量与静态项

常量 DEFAULT_PAGE_BATCH_SIZE

当 [crate::parser::LiteParse::open_batch_session] 的调用方没有指定批大小时,每批处理的页数。小到足以让实体化的结果保持可控,大到足以让每批一次的文档重开开销保持很低(在一份 457 页的文档上,这个批大小约占 13%,批大小取 50 时~约 4%)。

pub const DEFAULT_PAGE_BATCH_SIZE: usize = 25;

常量 DEFAULT_DPI

OCR 位图与截图的默认渲染分辨率(LiteParseConfig::dpi)。

pub const DEFAULT_DPI: f32 = 150.0;

枚举 LiteParseError

pub enum LiteParseError {
    Pdf(pdfium::PdfiumError),
    Io(std::io::Error),
    Json(serde_json::Error),
    Image(image::ImageError),
    Ocr(String),
    Conversion(String),
    Config(String),
    Other(String),
}

枚举变体

Pdf(pdfium::PdfiumError)

Io(std::io::Error)

Json(serde_json::Error)

Image(image::ImageError)

Ocr(String)

Conversion(String)

Config(String)

Other(String)

模块 glyph_resolver

可选的树外(out-of-tree)字形还原钩子。

对于缺失或损坏 /ToUnicode 的字体,liteparse 内置的还原方式是:PostScript 字形名 → Adobe Glyph List,再用内嵌字体程序的反向 cmap(见 [crate::extract])。它是确定性的,但解不开那些字形名与 cmap 同样是垃圾的问题字体。[GlyphResolver] 让调用方接入更强的还原策略 —— 例如「字形轮廓 → Unicode 数据库」—— 而 liteparse 不必背上这份依赖。

解析器拿到的是字形矢量轮廓(路径线段),而不是 pdfium 句柄,因此实现自身不需要 pdfium,也与 liteparse 的字体内部保持解耦。它只在万不得已时被调用:某个字形已被 liteparse 判定不可信、且内置还原已经失败。

pub mod glyph_resolver { /* ... */ }

Trait

Trait GlyphResolver

从字形的矢量轮廓还原出 liteparse 内置 cmap/AGL 还原无法解码的字形所对应的 Unicode 文本。

实现都在树外(发布的 @llamaindex/liteparse 不自带任何 resolver)。请用 [crate::LiteParse::with_glyph_resolver] 注入一个。

pub trait GlyphResolver: Send + Sync {
    /* Associated items */
}

必需项

必需方法

  • resolve: 依据轮廓还原一个字形。

提供的方法

  • fn resolve_codepoint(self: &Self, segments: &[(i32, f32, f32)]) -> Option<u32> { /* ... */ }

    把字形还原成单个码点,不做连字展开

常量与静态项

常量 GLYPH_RESOLVER_FONT_SIZE

在把字形路径线段交给 [GlyphResolver] 之前,采样时使用的字号(单位:点)。

以轮廓哈希为键的 resolver 必须正好在这个字号上采样,键才能对得上。

pub const GLYPH_RESOLVER_FONT_SIZE: f32 = 10.0;

模块 layout

markdown 分类器所做块拆解的公开、可序列化视图。

分类器内部的 Block 是一个带逐变体载荷的 Rust enum。这种形态无法跨越 napi 或 PyO3 边界 —— 两者都不支持携带数据的 enum —— 所以公开类型是一个由 kind 区分的扁平结构体,变体专属字段以 Option 形式存在。这与本 crate 已有的 StructureAttributeValue 暴露方式一致,并让 Rust、JSON、Node、Python 与 WASM 共用同一种块形态,而不是分裂成三种。

凡是不适用于该块 kind 的字段都为 None,序列化时会被跳过,因此一个标题序列化成 {kind, text, level, bbox},而不是一堆 null。

pub mod layout { /* ... */ }

结构体 LayoutCell

一个表格单元格:它渲染出的文本与它占据的区域。

背后没有墨迹的单元格,其 bbox 为 None —— 例如为补齐参差网格而插入的填充,或在估算位置(而非观察到的边界)处拆开的合并跨度的一半。

pub struct LayoutCell {
    pub text: String,
    pub bbox: Option<crate::types::Rect>,
    pub colspan: Option<u16>,
    pub rowspan: Option<u16>,
}

字段

名称类型文档
textString
bboxOption<crate::types::Rect>
colspanOption<u16>合并跨度,只出现在 merged_table 单元格上(且只在大于 1 时)。被邻格跨度吸收的单元格会整行缺席,与 HTML 的占位模型一致。
rowspanOption<u16>

结构体 LayoutBlock

一个分类后的块,以及它在页面上的位置。

由 kind 区分块的种类;每个字段各自适用于哪些种类见字段说明。块按阅读顺序出现,与 markdown 渲染器输出它们的顺序一致,因此这里的第 N 个块就是该页 markdown 里的第 N 个块。

pub struct LayoutBlock {
    pub kind: String,
    pub text: Option<String>,
    pub level: Option<u8>,
    pub bold: bool,
    pub italic: bool,
    pub ordered: Option<bool>,
    pub marker: Option<String>,
    pub lines: Option<Vec<String>>,
    pub lang: Option<String>,
    pub header: Option<Vec<LayoutCell>>,
    pub rows: Option<Vec<Vec<LayoutCell>>>,
    pub header_rows: Option<usize>,
    pub id: Option<String>,
    pub format: Option<String>,
    pub bbox: Option<crate::types::Rect>,
}

字段

名称类型文档
kindString取自 heading、paragraph、list_item、code、table、merged_table、grid_fallback、rule、figure。
textOption<String>带文字的那些种类(heading、paragraph、list_item)的渲染文本。表格文字在 header/rows 里;代码与网格文字在 lines 里。
levelOption<u8>标题层级(1–6),或 list_item 的列表嵌套深度。
boldbool块内文字是否整体加粗 / 倾斜。仅 paragraph 与 list_item;为 false 时省略。
italicbool
orderedOption<bool>list_item:列表是否有序,以及标记在页面上原样出现的样子(138.、iii)、•)。
markerOption<String>
linesOption<Vec<String>>code 与 grid_fallback 的逐行原文。
langOption<String>为 code 尽力而为给出的语言提示。
headerOption<Vec<LayoutCell>>table:检测到表头时的表头行。
rowsOption<Vec<Vec<LayoutCell>>>table:正文行。merged_table:全部行(表头行在前,数量由 header_rows 给出);行是参差的 —— 被邻格跨度覆盖的单元格缺席。
header_rowsOption<usize>merged_table:rows 开头有几行是表头行。
idOption<String>figure:图片在页内的 id 与其编码格式,与 markdown 渲染器发出的 img_{id}.{format} 目标一致。
formatOption<String>
bboxOption<crate::types::Rect>该块占据的页面区域,坐标空间与 text_items 相同(左上原点、72 DPI 视口)。它是构成该块的所有来源行的并集,因此换行标题或多行段落会上报整条区域。块没有页面几何可依时为 None。

模块 parser

LiteParse 编排器:输入解析、配置,以及固定的解析顺序。

不变式:parse() 的每一步都必须经由 [crate::stages]。本文件只掌握顺序以及「配置→阶段」的接合;它不得直接伸手进 extract、ocr_merge、projection 或 markdown_layout,否则自己编排阶段的调用方就无法再复现 parse()。tests/stages_compose.rs 正是对这一等价性的断言。

pub mod parser { /* ... */ }

结构体 ParseResult

解析一篇文档的结果。

pub struct ParseResult {
    pub total_pages: u32,
    pub pages: Vec<crate::types::ParsedPage>,
    pub page_errors: Vec<crate::types::PageError>,
    pub text: String,
    pub outline: Vec<crate::types::OutlineTarget>,
    pub images: Vec<crate::types::ExtractedImage>,
    pub screenshots: Vec<ScreenshotResult>,
    pub image_error_count: u32,
    pub form_type: Option<i32>,
    pub creator: Option<String>,
    pub producer: Option<String>,
    pub doc_meta: Option<crate::types::DocumentMetadata>,
    pub xfa_packets: Option<Vec<crate::types::XfaPacket>>,
}

字段

名称类型文档
total_pagesu32源文档的总页数,指应用 target_pages 或 max_pages 限制之前的总数。
pagesVec<crate::types::ParsedPage>投影过文字版面的解析页。
page_errorsVec<crate::types::PageError>开启 continue_on_page_error 时收集到的页级 PDFium 抽取失败。
textString整篇文档的文本,由所有页拼接而成。
outlineVec<crate::types::OutlineTarget>文档大纲(书签),若存在。markdown 输出器在未标签化的 PDF 上把它作为高优先级标题来源。
imagesVec<crate::types::ExtractedImage>从文档抽取出的位图。除非解析器配置了 extract_images,否则为空。每条记录带着 markdown 输出器所引用的同一 id 与 format,因此调用方无需解析 markdown 就能把它们对应起来。
screenshotsVec<ScreenshotResult>以 PNG 编码的页面截图。除非启用 extract_screenshots,否则为空。
image_error_countu32无法抽取的内嵌图片对象数量。一张坏图片不会让整篇文档的解析失败。
form_typeOption<i32>PDFium 表单类型(0 无、1 AcroForm、2 XFA 完整、3 XFA 前景),只在启用表单字段抽取时出现。
creatorOption<String>文档 /Info 中的 Creator 项,若存在。
producerOption<String>文档 /Info 中的 Producer 项,若存在。
doc_metaOption<crate::types::DocumentMetadata>文档来源元数据(日期、版本/安全、签名、增量保存标记、trailer ID、原始 XMP 以及源文件大小)。仅在启用 extract_document_metadata 时出现;对由非 PDF 格式转换而来的输入为 None。
xfa_packetsOption<Vec<crate::types::XfaPacket>>原始 XFA 数据包,仅在启用 extract_xfa_packets 时出现。Some([]) 表示抽取已在非 XFA 文档上运行过。

结构体 ScreenshotResult

渲染单页截图的结果。

pub struct ScreenshotResult {
    pub page_num: u32,
    pub width: u32,
    pub height: u32,
    pub image_bytes: Vec<u8>,
    pub is_solid_fill: bool,
    pub rects: Vec<crate::types::ScreenshotRect>,
}

字段

名称类型文档
page_numu32
widthu32
heightu32
image_bytesVec<u8>
is_solid_fillbool每个像素同色时为 true(渲染后为空白页)。
rectsVec<crate::types::ScreenshotRect>在位图中检测到的实心矩形/直线(视口坐标)。仅在 LiteParseConfig::detect_screenshot_rects 开启时填充。

结构体 LiteParse

LiteParse 的主编排器。

线程安全

LiteParse 是 Send + Sync,可以跨线程共享(例如放在 Arc 后面,或在多线程 tokio 运行时里并发使用)。

PDFium 本身不是线程安全的,所以所有 PDFium FFI 工作 —— 文档加载、页面渲染、文字抽取 —— 都要经由 [pdfium::Library] 持有的进程级全局锁串行化。对调用方而言,这意味着并发的 parse_* / screenshot* 调用是安全的,但它们的 PDFium 部分会顺序执行。OCR 阶段与网格投影(在 OCR 密集的文档上占据大部分运行时间)在锁之外运行,保持完全并发。

pub struct LiteParse {
    // Some fields omitted
}

方法

  • pub fn new(config: LiteParseConfig) -> Self { /* ... */ }
  • pub fn with_ocr_engine(self: Self, engine: std::sync::Arc<dyn OcrEngine>) -> Self { /* ... */ }

    覆盖 OCR 引擎。一旦设置,无论

  • pub fn with_glyph_resolver(self: Self, resolver: std::sync::Arc<dyn crate::GlyphResolver>) -> Self { /* ... */ }

    注入一个字形还原钩子。一旦设置,liteparse 判定为

  • pub fn extract_request<''a>(self: &''a Self, target_pages: Option<&''a [u32]>, max_pages: usize) -> stages::ExtractRequest<''a> { /* ... */ }

    整次解析所用的 extract 阶段请求,由配置推导而来。

  • pub fn ocr_render_options(self: &Self, grayscale: bool, extracted: &stages::ExtractedPages) -> stages::OcrRenderOptions { /* ... */ }

    整次解析所用的 OCR 渲染阶段选项,由配置推导

  • pub fn screenshot_options(self: &Self, continue_on_page_error: bool) -> stages::ScreenshotOptions { /* ... */ }

    截图阶段的选项,由配置推导。parse() 会传入

  • pub fn block_options<''a>(self: &Self, outline: &''a [OutlineTarget]) -> stages::BlockOptions<''a> { /* ... */ }

    块分类阶段的选项,由配置推导。

  • pub fn content_filters(self: &Self) -> stages::ContentFilters<''_> { /* ... */ }

    内容过滤阶段的选项,由配置推导而来。

  • pub fn ocr_engine(self: &Self) -> Result<Option<std::sync::Arc<dyn OcrEngine>>, LiteParseError> { /* ... */ }

    一次解析将要使用的 OCR 引擎:设置了覆盖就用覆盖,否则用

  • pub async fn is_complex(self: &Self, input: PdfInput) -> Result<Vec<stages::PageComplexityStats>, LiteParseError> { /* ... */ }

    判定文档中每一页的复杂度,返回一个向量

  • pub async fn parse(self: &Self, input: &str) -> Result<ParseResult, LiteParseError> { /* ... */ }

    从文件路径解析文档,返回结构化结果。

  • pub async fn parse_input(self: &Self, input: PdfInput) -> Result<ParseResult, LiteParseError> { /* ... */ }

    从文件路径或原始字节解析文档。

  • pub fn parse_from_pages(self: &Self, pages: Vec<Page>, outline: Vec<OutlineTarget>) -> ParseResult { /* ... */ }

    从预先抽取好的页面解析,跳过 PDFium 的文字抽取。

  • pub fn parse_from_blocks(self: &Self, pages: Vec<Page>, page_blocks: Vec<Vec<stages::PositionedBlock>>, all_blocks: Option<Vec<stages::PositionedBlock>>, outline: Vec<OutlineTarget>, images: Vec<crate::types::ExtractedImage>, page_stats: Vec<Option<stages::PageComplexityStats>>) -> Result<ParseResult, LiteParseError> { /* ... */ }

    直接由块构建输出:调用方自行掌控块级

  • pub async fn screenshot(self: &Self, input: &str, page_numbers: Option<Vec<u32>>) -> Result<Vec<ScreenshotResult>, LiteParseError> { /* ... */ }

    生成文档页面的截图,返回 PNG 字节。

  • pub async fn screenshot_input(self: &Self, input: PdfInput, page_numbers: Option<Vec<u32>>) -> Result<Vec<ScreenshotResult>, LiteParseError> { /* ... */ }

    从文件路径或原始字节生成截图。

  • pub fn config(self: &Self) -> &LiteParseConfig { /* ... */ }
  • pub async fn open_batch_session(self: &Self, input: PdfInput, batch_size: usize) -> Result<ParseSession, LiteParseError> { /* ... */ }

    为「内存有界的批量解析」打开一份文档。

结构体 ParseSession

只打开一次、按内存有界的页批次解析的文档。

pub struct ParseSession {
    // Some fields omitted
}

方法

  • pub fn total_pages(self: &Self) -> u32 { /* ... */ }

    源文档的总页数,指 max_pages 或分批之前的总数。

  • pub async fn next_batch(self: &mut Self) -> Result<Option<ParseBatch>, LiteParseError> { /* ... */ }

    解析并返回下一批,或在范围内的每一页都已处理完毕时返回 None。

结构体 ParseBatch

来自 [ParseSession] 的一批页面。

pub struct ParseBatch {
    pub start_page: u32,
    pub end_page: u32,
    pub result: ParseResult,
}

字段

名称类型文档
start_pageu32本批次的第一页源页号,从 1 开始。
end_pageu32本批次的最后一页源页号,从 1 开始且含该页。
resultParseResultstart_page..=end_page 范围内的页,按普通结果解析。

模块 raw_text

原始文字项:pdfium 的文字流,配合固定的、不含启发式的切分。

[extract_raw_text_items] 是 [crate::extract] 里分段器的底层对应物。它不施加任何版面启发式 —— 没有基于间距的行/词合并、不跳过隐形文字、不做连字展开、不做标点规范化、不去重 —— 因此它的输出是 pdfium 所报内容的稳定函数,消费方可以在其之上自建切分。被已知矩形裁剪隐藏的字形会在分组前被剔除;部分被裁剪的字形只要其宽松框与裁剪区相交就整份保留。未知裁剪则保留文字。

规则:

  • 一个项是同一个文本对象的同一角度上的一段字形。若某个字形的文本对象与该项首字形不同,或角度与之相差超过 0.01 rad,就开启一个新项。
  • pdfium 生成的 \r 或 \n 会结束当前项并被丢弃。
  • 其他所有生成的字形,以及每个 ASCII 空白字形(\t..\r 与空格;U+00A0、U+3000 等不算)都会先追加、再结束该项。因此一个 pdfium 合成的空格永远是项的最后一个字形 —— [RawTextItem::trailing_space_generated] 报的就是它。
  • 边界是各字形宽松框的并集。角度、颜色、marked-content id、字体与字体度量取自首字形。text_width 累加逐字形的推进宽度。
  • 角度是该字形文本矩阵的基线方向(取其第一列的 atan2(b, a)),而不是 pdfium 的 FPDFText_GetCharAngle:错切(斜体)字体的错量落在第二列,它不该改变阅读方向。并与页面 /Rotate 一起折叠到 [0, 2π)。
  • [RawTextItem::grounding_bounds] 是该项真实字形的紧框:所有非生成、非空白的字形(在问题字体还原之后判定)都被投影到沿基线与垂直基线两个方向,极值重新居中为一个矩形,再按角度绕其中心旋转。没有符合条件的字形时为 None。错切字体的宽松框会与下一个词重叠,这个框不会。正交、未错切的文字投影其严格字形框的四角。旋转或错切的文字则投影字形轮廓的点(见 [glyph_outline_support]):pdfium 的字符框在页面坐标里已经包住旋转后的字形,其空荡荡的四角无法被旋转回墨迹。轮廓无法替代实际描绘的字形 —— 描边渲染模式、Type3 以及非 Identity-H 的 CID 字体、读不到的几何 —— 保留其严格框。
  • [RawTextItem::baseline_gap] 只在这样一种项上测量:它是水平字体(Type1、TrueType,或 Identity-H 的 CID 字体)两个真实字形之间唯一一个 pdfium 生成的空格,且这些字形共享同一基线方向;取上一字形原点到下一字形原点的推进量减去上一个字形的宽度,单位是页面点。在外框无法反映真实间距时,它报出真正的分离程度。相邻字形不合格,或原点倒退(pdfium 在旋转页上反转对象顺序时会这样)时为 None。
  • [append_raw_widget_text_items] 追加可见表单控件外观所绘制的文字 —— 在它们被压平之前,pdfium 的文字 API 不会报出这些内容。
  • 一个字体被称为“问题字体”,条件是:它被内嵌且其名称/类型符合子集字体启发式,或者任意非生成字形解码到了控制码点或私用区码点。pdfium 无法映射到 Unicode 的字形解码为 0,因而也计入 —— 所以每个 Type3 项都算问题字体。
  • 配有 [GlyphResolver] 时,问题项里每个非生成字形都会被重新解码:先试 Type3 的字形名,再把字形轮廓交给 resolver。无法识别的字形变成空格。没有 resolver 时,文字保持 pdfium 解码出的样子。
  • 文本按 C 字符串语义由字形码点构建:码点为 0(无 Unicode 映射的字形)会提前终止文本;不是合法 Unicode 标量值的码点(代理项,或大于 U+10FFFF)会让整个项被丢弃。

坐标是按每个字形经由 [Page::bounds_to_viewport] 换算的 —— 即精确的 FPDF_PageToDevice 量化 —— 而不是仿射近似 [Page::viewport_transform],因此框可以逐位复现。视口会按页面的 /UserUnit 缩放,与 liteparse 各处一致。

pub mod raw_text { /* ... */ }

结构体 RawTextItem

一个原始文字项,处于视口坐标空间(左上原点、72 dpi 点)。

pub struct RawTextItem {
    pub text: String,
    pub char_codes: Vec<u32>,
    pub glyph_names: Option<Vec<String>>,
    pub angle_radians: f32,
    pub text_width: f32,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub grounding_bounds: Option<pdfium::RectF>,
    pub baseline_gap: Option<f64>,
    pub mcid: Option<i32>,
    pub font_name: String,
    pub font_size: f32,
    pub font_weight: i32,
    pub font_height: f32,
    pub font_ascent: f32,
    pub font_descent: f32,
    pub font_is_buggy: bool,
    pub trailing_space_generated: bool,
    pub fill_color: Option<u32>,
    pub stroke_color: Option<u32>,
}

字段

名称类型文档
textString字形码点的 UTF-8。保留空白,包括尾随空格;NUL 与非法标量值的语义见模块文档。
char_codesVec<u32>按页顺序每字形一项:内容流里的原始字符码,pdfium 生成的字形为 0。
glyph_namesOption<Vec<String>>仅 Type3 字体为每字形给一项,与 char_codes 平行:字体把该码点绑定到的 PostScript 字形名,未绑定时为 ""。其他所有字体类型为 None。
angle_radiansf32逆时针旋转角(弧度),已折叠页面旋转,取值在 [0, 2π)。保留为弧度,便于消费方按自己需要的精度换算。
text_widthf32各字形推进宽度之和(文本空间)。
xf32
yf32
widthf32
heightf32
grounding_boundsOption<pdfium::RectF>该项真实字形的紧框,形态为一个矩形,需按 angle_radians 绕其中心旋转;见模块文档。视口坐标空间。
baseline_gapOption<f64>跨唯一一个生成空格的推进间隙,单位页面点;见模块文档。相邻字形重叠时为零或负。
mcidOption<i32>首字形所属文本对象的 marked-content id,若存在。
font_nameString基础字体名,已按 pdfium 的方式剥去子集标签;首字形没有文本对象、或该对象无字体时为 ""。
font_sizef32
font_weighti32
font_heightf32font_size 乘以文本矩阵的纵向缩放;首字形没有文本对象时为 0。
font_ascentf32字体未暴露度量时为 0。
font_descentf32字体未暴露度量时为 0。
font_is_buggybool
trailing_space_generatedbool最后一个字形是 pdfium 合成的空格,而非内容流里的空格字形。
fill_colorOption<u32>首个字形的填充颜色,打包为 ARGB;仅当其色彩空间可用 RGB 表达时。
stroke_colorOption<u32>首个字形的描边颜色,打包为 ARGB;可表达时。

函数 extract_raw_text_items

抽取 text_page 的原始文字项。view_box 是页面的裁剪框([Page::view_box]);glyph_resolver 是针对问题字体的、可选的基于轮廓的还原(见模块文档),传 None 则问题文字保持原解码结果。

pub fn extract_raw_text_items(page: &pdfium::Page<''_, ''_>, text_page: &pdfium::TextPage<''_, ''_>, view_box: &pdfium::RectF, glyph_resolver: Option<&dyn GlyphResolver>) -> Vec<RawTextItem> { /* ... */ }

函数 append_raw_widget_text_items

追加 page_index 页上可见表单控件外观所绘制的文字 —— [extract_raw_text_items] 看不到这些内容:pdfium 的文字 API 只有在外观字形被压平进页面内容后才会报出它们。外观在一个页面的私有副本上压平([Document::widget_appearance_copy]),并用同样的规则抽取,然后追加到 items —— 但某个控件项若在相同几何位置重复了已有项的文字则除外(某些生产者会在两处都输出它)。追加的项不带 marked-content id:外观的 MCID 不属于页面的结构树。

当副本无法构建或读取时返回 false;此时 items 保持不变,调用方继续沿用已有的页面文字。没有此类控件的页是一个无副作用的 true。

pub fn append_raw_widget_text_items(doc: &pdfium::Document<''_>, page: &pdfium::Page<''_, ''_>, page_index: i32, glyph_resolver: Option<&dyn GlyphResolver>, items: &mut Vec<RawTextItem>) -> bool { /* ... */ }

结构体 SearchOptions

搜索文字项的选项。

pub struct SearchOptions {
    pub phrase: String,
    pub case_sensitive: bool,
}

字段

名称类型文档
phraseString
case_sensitivebool

函数 search_items

在文字项中搜索短语匹配,返回合成的合并项。

连续的文字项会被拼接后搜索。当一个短语跨多个项时,结果是一个合并后的单项,带合并的边界框与匹配到的文字。字体元数据取自第一个匹配到的项。

pub fn search_items(items: &[crate::types::TextItem], options: &SearchOptions) -> Vec<crate::types::TextItem> { /* ... */ }

模块 stages

以公开阶段函数形式给出的解析流水线。

LiteParse::parse 是一串固定顺序的阶段:open → orientation → extract → complexity → OCR render → recognition → OCR merge → content filters → grid projection → block classification → markdown rendering。本模块把每个阶段暴露成作用于可序列化类型的函数,于是调用方可以自行跑完同一串阶段,并在阶段之间插入自己的输入 —— 自己的 OCR 引擎、自己的页选择、额外的块 —— 也可以在任意两个阶段之间架一道进程边界。

阶段分成两类。绑定 pdfium 的阶段接收一个已打开的 [Document],必须在打开它的那个 [Library] 存活期间运行(PDFium 是单线程的,背后由进程级全局锁保护,所以这些区段要尽量短,且绝不要把一个 Document 跨 .await 持有)。纯函数 阶段接收并返回普通数据,可以在任何地方运行。

阶段函数类型
open + orientation[open], [apply_orientation]pdfium
document facts[outline], [xfa_packets], [document_metadata]pdfium
extract[extract]pdfium
complexity[page_complexity], [layout_complexity]pdfium / pure
OCR[render_for_ocr] → [recognize] → [merge_ocr]pdfium / any / pure
content filters[apply_content_filters]pure
projection[project]pure
markdown[document_signals] → [extract_blocks] → [render_page_markdown]pure
screenshots[screenshots]pdfium

[Document] 与 [Library] 是把 pdfium crate 的类型原样重导出,因此那个 crate 的句柄 API 也是本模块契约的一部分。

pub mod stages { /* ... */ }

结构体 ExtractRequest

[extract] 从文档里取出哪些内容。

pub struct ExtractRequest<''a> {
    pub target_pages: Option<&''a [u32]>,
    pub max_pages: usize,
    pub extract_links: bool,
    pub glyph_resolver: Option<&''a dyn crate::GlyphResolver>,
    pub output: ExtractionOutputOptions,
}

字段

名称类型文档
target_pagesOption<&''a [u32]>要抽取的页(从 1 开始);None 表示全部页。
max_pagesusize抽取页数的上限,在 target_pages 之后应用。
extract_linksbool把链接批注解析到它所覆盖的文字项上。
glyph_resolverOption<&''a dyn crate::GlyphResolver>针对问题字体的兜底字形还原(见 [crate::GlyphResolver])。
outputExtractionOutputOptions要产出哪些可选输出(图片、逐词框、表单字段……)。

结构体 OcrWindow

滑动渲染窗口内正在进行的 OCR 识别。

[recognize] 会等它拿到的整批位图全部完成。而 LiteParse::parse 改为最多只并行 num_workers 个识别,一个完成就立刻渲染下一页,因此某一页变慢不会让其他 worker 空转。当每一轮都用 [OcrWindow::render_next] 渲染时(它渲染的页数不会超过空闲槽位数),位图内存就被 num_workers 约束住。

原生识别跑在 Tokio 的阻塞线程上。在 WASM 上,识别的 future 可以 await JavaScript 的 promise。

pub struct OcrWindow {
    // Some fields omitted
}

方法

  • pub fn new(engine: Arc<dyn OcrEngine>, language: &str, num_workers: usize) -> Self { /* ... */ }

    启动一个窗口,最多同时运行 num_workers 个识别。

  • pub fn available_capacity(self: &Self) -> usize { /* ... */ }

    还能提交多少张位图而不必等待。

  • pub fn render_next(self: &Self, document: &Document<''_>, pages: &[Page], start: usize, options: &OcrRenderOptions) -> Result<(Vec<OcrRaster>, usize), LiteParseError> { /* ... */ }

    [render_for_ocr] 的结果被限制在 available_capacity 之内

  • pub fn complete_ready(self: &mut Self) { /* ... */ }

    记录已经完成的识别,不做等待。

  • pub async fn complete_one(self: &mut Self) -> bool { /* ... */ }

    等到一个进行中的识别完成并记录它。返回

  • pub fn take_completed(self: &mut Self) -> Vec<PageOcrOutcome> { /* ... */ }

    按提交顺序取出已完成的输出。对 finish 的后续调用

  • pub async fn submit(self: &mut Self, raster: OcrRaster) { /* ... */ }

    为一张位图启动识别,若窗口已满则先等待空闲槽位

  • pub async fn finish(self: Self) -> Vec<PageOcrOutcome> { /* ... */ }

    等待剩余的识别并返回全部输出,顺序

  • pub async fn finish_and_merge(self: Self, pages: &mut [Page], ocr_failure_fatal: bool, emit_word_boxes: bool) -> Result<(), LiteParseError> { /* ... */ }

    先 finish,再用 [merge_ocr] 把输出并入 pages。

结构体 ContentFilters

调用方要求的文字项过滤,作用于 OCR 合并与投影之间。

pub struct ContentFilters<''a> {
    pub crop_box: Option<&''a crate::config::CropBox>,
    pub skip_diagonal_text: bool,
}

字段

名称类型文档
crop_boxOption<&''a crate::config::CropBox>只保留完全落在保留页面区域内的项。
skip_diagonal_textbool丢弃倾斜文字(水印、旋转盖章)。

结构体 DocumentSignals

块分类器需要的全文档级信号:对所有页计算一次,再由 [extract_blocks] 逐页应用。标题层级是相对文档的正文字号排出的,而滚动页眉/页脚是跨页重复出现的那些行 —— 两者都无法只看一页就判定。分批分类页面的调用方必须先对整篇文档计算它,否则标题层级会在批次之间漂移。

pub struct DocumentSignals {
    pub body_size: f32,
    pub heading_map: Vec<(f32, u8)>,
    pub header_footer: std::collections::HashSet<String>,
}

字段

名称类型文档
body_sizef32主导正文字号(点);没有任何带字号的行时为 0.0。
heading_mapVec<(f32, u8)>(font_size, heading_level) 键值对,字号从大到小,层级 1..=6。
header_footerstd::collections::HashSet<String>需要抑制的滚动页眉/页脚文本(归一化后)。当设置了 keep_headers_footers,或文档短到无法判定时为空。

结构体 BlockOptions

除信号之外,[extract_blocks] 的文档级输入。

pub struct BlockOptions<''a> {
    pub outline: &''a [crate::types::OutlineTarget],
    pub image_mode: crate::config::ImageMode,
    pub keep_headers_footers: bool,
}

字段

名称类型文档
outline&''a [crate::types::OutlineTarget]文档大纲;属于该页的条目在未标签化 PDF 上作为高优先级标题来源。
image_modecrate::config::ImageMode图形是否以及如何在块列表中出现。
keep_headers_footersbool关闭滚动版式抑制(信号里的跨页集合与单页检测器都关掉)。

结构体 ScreenshotOptions

[screenshots] 渲染页面的方式。

pub struct ScreenshotOptions {
    pub dpi: f32,
    pub detect_rects: bool,
    pub render_form_fields: bool,
    pub continue_on_page_error: bool,
}

字段

名称类型文档
dpif32
detect_rectsbool在位图里检测实心矩形/直线(ScreenshotResult::rects)。
render_form_fieldsbool绘制表单字段外观(会执行文档动作)。
continue_on_page_errorbool渲染失败的页跳过而不是让整个调用失败。

函数 open

打开 input 并应用逐页的朝向修正。

/Rotate 的改写只存在于已打开的文档里,因此对同一输入的每次重新打开(抽取、OCR 各轮、截图)都必须经由本函数、并传入同样的 corrections,才能看到同样的页面几何。

pub fn open<''lib>(lib: &''lib Library, input: &crate::types::PdfInput, password: Option<&str>, corrections: &[crate::config::PageOrientationCorrection]) -> Result<Document<''lib>, crate::error::LiteParseError> { /* ... */ }

函数 apply_orientation

把 corrections 里列出的页反向旋转,使其内容正向可读。[open] 已经做了这件事;只有在以其他方式打开的文档上才需要直接调用它。

pub fn apply_orientation(document: &Document<''_>, corrections: &[crate::config::PageOrientationCorrection]) -> Result<(), crate::error::LiteParseError> { /* ... */ }

函数 repair_acroform

属性:

  • Other("#[attr = CfgTrace([Not(NameValue { name: \"target_arch\", value: Some(\"wasm32\"), span: crates/liteparse/src/stages.rs:95:11: 95:33 (#0) }, crates/liteparse/src/stages.rs:95:10: 95:34 (#0))])]")

重写那些控件与其页面脱链(orphaned)的 AcroForm,让表单字段抽取能够看到它们。需要重写时返回修复后的输入;文档本身没问题时返回 None。返回值就是用于抽取的 [open] 输入;而来源事实仍应取自原始输入。

pub fn repair_acroform(lib: &Library, input: &crate::types::PdfInput, password: Option<&str>) -> Option<crate::types::PdfInput> { /* ... */ }

函数 outline

遍历文档大纲(书签)。它是文档级的,且比打开文档贵数倍,因此按页批量解析的调用方应当只做一次。

pub fn outline(document: &Document<''_>) -> Vec<crate::types::OutlineTarget> { /* ... */ }

函数 xfa_packets

来自文档 /XFA 数组的原始 XFA 数据包。非 XFA 文档返回空。

pub fn xfa_packets(document: &Document<''_>) -> Vec<crate::types::XfaPacket> { /* ... */ }

函数 document_metadata

来源元数据(日期、安全、签名、增量保存标记、XMP)。input 必须是这些事实所描述的那个文件:传原始输入,而不是 AcroForm 修复后或格式转换后的副本。

pub fn document_metadata(input: &crate::types::PdfInput, document: &Document<''_>) -> crate::types::DocumentMetadata { /* ... */ }

函数 extract

从一个已打开的文档里抽取文字项、图形、结构节点以及(可选的)图片。这是唯一一个通过 PDFium 读取文字内容的阶段;下游一切都作用在返回的 [Page] 上。

开启 extract_form_fields 时,抽取可能会把某些页的控件批注压平进页面内容,以恢复其中的文字。这会改变已打开的文档:随后在同一文档上带 render_form_fields 调用 [screenshots] 就会把这些控件绘制两次,而从重新打开的文档得到的 OCR 位图必须再把同样的页压平一次才能对齐。返回的 flattened_form_widgets / flattened_page_numbers 说明了发生了什么;[screenshots_need_pristine_document] 与 LiteParse::ocr_render_options 会据此给出正确的后续做法。

pub fn extract(document: &Document<''_>, request: &ExtractRequest<''_>) -> Result<ExtractedPages, crate::error::LiteParseError> { /* ... */ }

函数 page_complexity

为一张已抽取的页打分:它是否需要 OCR,以及原因。它通过 PDFium 读取页面对象(图片、填充路径),因此必须针对该页抽取时所用的文档运行。layout 保持未设置;投影之后的那一半见 [layout_complexity]。

pub fn page_complexity(document: &Document<''_>, page: &crate::types::Page) -> Result<PageComplexityStats, crate::error::LiteParseError> { /* ... */ }

函数 layout_complexity

为投影后的页面给出版面难度信号(分栏、表格、密集图形)。纯函数;填充 PageComplexityStats::layout。

pub fn layout_complexity(page: &crate::types::ParsedPage) -> LayoutComplexityStats { /* ... */ }

函数 render_for_ocr

把 pages[start..] 中需要 OCR(或 options.selection 指定)的页面位图化,取到 options.max_rasters 为止。返回位图列表以及下次应当续起的下标,于是长文档可以按有界的若干轮跑完。在 await 识别之前请把 [Document] 丢弃。

pub fn render_for_ocr(document: &Document<''_>, pages: &[crate::types::Page], start: usize, options: &OcrRenderOptions) -> Result<(Vec<OcrRaster>, usize), crate::error::LiteParseError> { /* ... */ }

函数 recognize

让一个 [OcrEngine] 跑完这批位图,最多同时 num_workers 个。纯识别;失败以逐条结果的形式给出而非报错。在每个目标上结果都按输入顺序返回。自带 OCR 服务的调用方可以跳过本函数,直接用 [OcrRaster] 的事实与其引擎给出的词框(位图像素空间)构造 [PageOcrOutcome]。

pub async fn recognize(rasters: Vec<OcrRaster>, engine: std::sync::Arc<dyn OcrEngine>, language: &str, num_workers: usize) -> Vec<PageOcrOutcome> { /* ... */ }

函数 merge_ocr

把识别结果就地并入 pages:丢弃不可用的原生文字、过滤引擎产物、把存活的结果作为 OCR 文字项(视口点)追加。只有当所有结果都失败、且其中失败的页里没有可用原生文字时(ocr_failure_fatal)才报错。

emit_word_boxes 要传 LiteParseConfig::effective_emit_word_boxes:每个引擎结果就是一个词,因此这是 OCR 路径唯一能挂上词框的地方,且它必须与抽取阶段所用的取值一致 —— 否则一次运行只会让原生文字带上有词框。见 ExtractionOutputOptions::emit_word_boxes。

pub fn merge_ocr(pages: &mut [crate::types::Page], outcomes: Vec<PageOcrOutcome>, ocr_failure_fatal: bool, emit_word_boxes: bool) -> Result<(), crate::error::LiteParseError> { /* ... */ }

函数 apply_content_filters

就地给 pages 应用 [ContentFilters]。它跑在 [merge_ocr] 之后,因此 OCR 文字也会被过滤;也跑在 [project] 之前,因此被移除的项绝不会进入输出。没有请求任何过滤时是空操作。

pub fn apply_content_filters(pages: &mut [crate::types::Page], filters: &ContentFilters<''_>) { /* ... */ }

函数 project

网格投影:把每页的项变成带空间排版的纯文本,并给出 markdown 各阶段所读取的逐行结构。纯函数且逐页进行,因此可以作用于任意页子集。

pub fn project(pages: Vec<crate::types::Page>) -> Vec<crate::types::ParsedPage> { /* ... */ }

函数 document_signals

对文档的每一页计算 [DocumentSignals]。

pub fn document_signals(pages: &[crate::types::ParsedPage], keep_headers_footers: bool) -> DocumentSignals { /* ... */ }

函数 extract_blocks

把一张投影后的页面分类成最终的块序列:标题、段落、列表、代码、表格、分隔线、图形 —— 已经完成版式抑制、分隔线去重与软连字符拼接。这正是 [render_page_markdown] 所渲染、ParsedPage::blocks 所报告的那套拆解。

表格检测会依据 TextItem.words 切开合并单元格,因此请用 LiteParseConfig::effective_emit_word_boxes 抽取,才能得到 parse() 报告的那些块。

对没有投影行的页(空白页,或纯 OCR 且没有字体元数据)返回 None:那里没有结构可报告,渲染会退回到围栏里的投影文本。

pub fn extract_blocks(page: &crate::types::ParsedPage, signals: &DocumentSignals, options: &BlockOptions<''_>) -> Option<Vec<PositionedBlock>> { /* ... */ }

函数 render_page_markdown

由页的块渲染该页的 markdown。分类结果为 None 的页会把它的投影文本放进一个 ```text 围栏里渲染,以免有任何内容被静默丢弃。

pub fn render_page_markdown(page: &crate::types::ParsedPage, blocks: Option<&[PositionedBlock]>) -> String { /* ... */ }

函数 layout_blocks

页内块的公开扁平视图(ParsedPage::blocks),其中块框已从投影坐标系映射回视口坐标空间。

pub fn layout_blocks(page: &crate::types::ParsedPage, blocks: &[PositionedBlock]) -> Vec<LayoutBlock> { /* ... */ }

函数 canonicalize_image_refs

把重复图片的图形引用改指向规范图片的文件名,作用于每一页的 markdown 与 full_text。只有规范图片会被写到磁盘,因此重复位置若仍写作 ![](img_p2_1.jpg) 就会引用一个并不存在的文件。

pub fn canonicalize_image_refs(pages: &mut [crate::types::ParsedPage], full_text: &mut String, images: &[crate::types::ExtractedImage]) { /* ... */ }

函数 screenshots_need_pristine_document

[screenshots] 是否必须跑在一份新打开的文档上,而不是 [extract] 所用那份。当抽取已把控件批注压平进页面内容,并且截图将通过表单环境绘制表单字段时为 true —— 在被改动的文档上这些控件会被画两遍。普通截图不受影响,因为压平提升的正是渲染器本来就会绘制的那些外观流。

pub fn screenshots_need_pristine_document(extracted: &ExtractedPages, options: &ScreenshotOptions) -> bool { /* ... */ }

函数 screenshots

把页面渲染为 PNG。page_numbers 从 1 开始;None 表示渲染全部页。

pub fn screenshots(document: &Document<''_>, page_numbers: Option<&[u32]>, options: &ScreenshotOptions) -> Result<Vec<ScreenshotResult>, crate::error::LiteParseError> { /* ... */ }

重导出

重导出 ExtractedPages

pub use crate::extract::ExtractedPages;

重导出 ExtractionOutputOptions

pub use crate::extract::ExtractionOutputOptions;

重导出 LayoutBlock

pub use crate::layout::LayoutBlock;

重导出 LayoutCell

pub use crate::layout::LayoutCell;

重导出 Block

pub use crate::markdown_layout::Block;

重导出 Cell

pub use crate::markdown_layout::Cell;

重导出 PositionedBlock

pub use crate::markdown_layout::PositionedBlock;

重导出 SpanCell

pub use crate::markdown_layout::SpanCell;

重导出 render_blocks

pub use crate::markdown_layout::render_blocks;

重导出 OcrResult

pub use crate::ocr::OcrResult;

重导出 ComplexityReason

pub use crate::ocr_merge::ComplexityReason;

重导出 LayoutComplexityReason

pub use crate::ocr_merge::LayoutComplexityReason;

重导出 LayoutComplexityStats

pub use crate::ocr_merge::LayoutComplexityStats;

重导出 OcrRaster

pub use crate::ocr_merge::OcrRaster;

重导出 OcrRenderOptions

pub use crate::ocr_merge::OcrRenderOptions;

重导出 PageComplexityStats

pub use crate::ocr_merge::PageComplexityStats;

重导出 PageOcrOutcome

pub use crate::ocr_merge::PageOcrOutcome;

重导出 ScreenshotResult

pub use crate::parser::ScreenshotResult;

重导出 Document

绑定 pdfium 的那些阶段所接收的 PDFium 句柄类型。重导出出来,调用方就不必直接依赖 pdfium crate。

pub use pdfium::Document;

重导出 Library

绑定 pdfium 的那些阶段所接收的 PDFium 句柄类型。重导出出来,调用方就不必直接依赖 pdfium crate。

pub use pdfium::Library;

结构体 DocumentMetadata

文档级来源元数据,来自 PDFium 加上对源 PDF 的有界流式扫描。所有字段都保持 optional,这样畸形的元数据绝不会阻碍文档本身被解析。

pub struct DocumentMetadata {
    pub creation_date: Option<String>,
    pub mod_date: Option<String>,
    pub file_version: Option<i32>,
    pub is_encrypted: Option<bool>,
    pub security_handler_revision: Option<i32>,
    pub permissions: Option<u64>,
    pub eof_section_count: Option<u32>,
    pub startxref_count: Option<u32>,
    pub trailer_id_pair_differs: Option<bool>,
    pub raw_file_size: Option<u64>,
    pub xmp: Option<String>,
    pub xmp_truncated: Option<bool>,
    pub signature_count: Option<u32>,
    pub signature_byte_range_reaches_eof: Option<bool>,
}

字段

名称类型文档
creation_dateOption<String>
mod_dateOption<String>
file_versionOption<i32>
is_encryptedOption<bool>
security_handler_revisionOption<i32>
permissionsOption<u64>
eof_section_countOption<u32>文件中字面的 %%EOF 标记。可粗略反映增量更新:内嵌的 PDF 附件与内容流里的文字都会把它撑大。
startxref_countOption<u32>文件中字面的 startxref 标记,注意事项同上。
trailer_id_pair_differsOption<bool>最后一个 trailer /ID 数组的两半是否不同 —— 通常意味着文件在创建后被更新过。在最后 1 MiB 里找不到十六进制字符串 /ID 对时为 None。
raw_file_sizeOption<u64>
xmpOption<String>文档目录的 /Metadata XMP 包,上限 64 KiB。文档没有 XMP、XMP 过大以致无法廉价解析(见 extract_document_metadata),或在 WASM 构建下时为 None。
xmp_truncatedOption<bool>目录的 XMP 流超过 64 KiB 上限、xmp 里只有前 64 KiB 时为 true。
signature_countOption<u32>
signature_byte_range_reaches_eofOption<bool>

结构体 TextItem

表示从 PDF 页面抽出的单个文字项,包含其内容、位置、尺寸、旋转与字体元数据。

pub struct TextItem {
    pub text: String,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub rotation: f32,
    pub font_name: Option<String>,
    pub font_size: Option<f32>,
    pub font_height: Option<f32>,
    pub font_ascent: Option<f32>,
    pub font_descent: Option<f32>,
    pub font_weight: Option<i32>,
    pub font_flags: Option<i32>,
    pub text_width: Option<f32>,
    pub font_is_buggy: bool,
    pub has_unicode_map_error: bool,
    pub mcid: Option<i32>,
    pub fill_color: Option<String>,
    pub stroke_color: Option<String>,
    pub char_codes: Vec<u32>,
    pub trailing_space_generated: bool,
    pub confidence: Option<f32>,
    pub link: Option<String>,
    pub strike: bool,
    pub words: Vec<WordBox>,
}

字段

名称类型文档
textString
xf32视口坐标空间(左上原点、72 DPI)。
yf32
widthf32
heightf32
rotationf32旋转角度(逆时针,已按页面旋转调整)。
font_nameOption<String>
font_sizeOption<f32>
font_heightOption<f32>文本矩阵给出的 font_size * scale_y —— 已计入 CTM 缩放。
font_ascentOption<f32>
font_descentOption<f32>
font_weightOption<i32>
font_flagsOption<i32>
text_widthOption<f32>各字形宽度之和(尽可能用 charcode 查表)。
font_is_buggybool字体编码是否有缺陷(私用区码点、TrueType 子集等)
has_unicode_map_errorbool该项中是否大部分字符都无法映射到 Unicode(例如没有 ToUnicode 映射的 Type3 字体)。此时文本内容是 PDFium 的字符码兜底结果,并不反映实际渲染的字形。
mcidOption<i32>来自 PDF 结构树的 Marked content ID。
fill_colorOption<String>填充颜色,ARGB 十六进制字符串(例如 “ff000000”)。
stroke_colorOption<String>描边颜色,ARGB 十六进制字符串。
char_codesVec<u32>来自 PDF 内容流的原始字符码。它们对应源字形而非 Unicode 标量值,因此连字展开产生的文本字符数可能多于本数组的条目数。
trailing_space_generatedbool尾随的源空格是否是 PDFium 合成的,而不是内容流里真实存在的空格字形。
confidenceOption<f32>OCR 置信度(0.0–1.0)。原生 PDF 文字为 None。
linkOption<String>当该项落在某个超链接批注的矩形内时的目标 URI。在 extract.rs 中填充;由 markdown 输出器消费。
strikebool是否有一条细水平描边/矩形横穿该项的纵向中段(删除线)。在 extract.rs 中填充;markdown 输出器据此把文字包进 ~~…~~。
wordsVec<WordBox>该项内部的逐词子框,按构建分段时看到的词间空格切分。一个分段会把若干词归在一起(只在行/列边界断开),因此这里给出词级几何以便做边界框归属。没有发生词切分的项(如来自 OCR 或只含单个记号的项)为空。仅用于内部/归属:公开 JSON 输出(output/json.rs)自建其视图、不含它,但它要跨越 napi 边界并必须活过阶段边界(见 stages),所以参与序列化。

方法

  • pub fn text_metadata(self: &Self, enabled: bool) -> TextMetadata<''_> { /* ... */ }

    该项的富元数据视图:enabled 时为真实值,否则全

结构体 TextMetadata

受 extract_text_metadata 支配的那批 TextItem 字段,并由 [TextItem::text_metadata] 预先设好开关。这个结构体界定了哪些字段算作富文本元数据:每个输出出口(CLI JSON、napi、python、wasm)都以它来构建公开的文字项,所以在这里新加一个元数据字段,若没在每个出口接线,就会在各处成为编译错误。

所有字段都是 Option/切片,因此即便 TextItem 上那些裸 bool 字段也能表达“未开启抽取”:None/空表示调用方没有选择开启,该字段必须从输出中省略。

pub struct TextMetadata<''a> {
    pub font_height: Option<f32>,
    pub font_ascent: Option<f32>,
    pub font_descent: Option<f32>,
    pub font_weight: Option<i32>,
    pub text_width: Option<f32>,
    pub font_is_buggy: Option<bool>,
    pub mcid: Option<i32>,
    pub fill_color: Option<&''a str>,
    pub stroke_color: Option<&''a str>,
    pub char_codes: Option<&''a [u32]>,
    pub trailing_space_generated: Option<bool>,
}

字段

名称类型文档
font_heightOption<f32>
font_ascentOption<f32>
font_descentOption<f32>
font_weightOption<i32>
text_widthOption<f32>
font_is_buggyOption<bool>
mcidOption<i32>
fill_colorOption<&''a str>
stroke_colorOption<&''a str>
char_codesOption<&''a [u32]>
trailing_space_generatedOption<bool>

结构体 WordBox

TextItem 内某个词的边界框,与父项处于同一视口坐标空间(左上原点、72 DPI)。text 是该词的内容,不含词间空格。

pub struct WordBox {
    pub text: String,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

字段

名称类型文档
textString
xf32
yf32
widthf32
heightf32

结构体 PageError

在启用「容错逐页错误」时无法抽取的那一页。

pub struct PageError {
    pub page_number: u32,
    pub message: String,
}

字段

名称类型文档
page_numberu32源页号(从 1 开始)。序列化为 page,以与 JSON 输出里逐页字段的兄弟项(pages[]、images[])保持一致。
messageString人类可读的抽取失败信息。

结构体 DocumentAnnotation

一条 PDF 页面批注。坐标与 [TextItem] 一样采用左上原点、72 DPI 的视口坐标空间。

pub struct DocumentAnnotation {
    pub subtype: String,
    pub contents: Option<String>,
    pub created: Option<String>,
    pub modified: Option<String>,
    pub title: Option<String>,
    pub rect: Option<Rect>,
    pub quadpoint_rects: Vec<Rect>,
    pub uri: Option<String>,
}

字段

名称类型文档
subtypeString
contentsOption<String>
createdOption<String>
modifiedOption<String>
titleOption<String>
rectOption<Rect>
quadpoint_rectsVec<Rect>
uriOption<String>

枚举 StructureAttributeValue

属性:

  • Other("#[serde(untagged)]")

标签 PDF 结构元素 /A 字典里的一个标量值。

pub enum StructureAttributeValue {
    Boolean(bool),
    Number(f32),
    String(String),
}

枚举变体

Boolean(bool)

Number(f32)

String(String)

结构体 StructureTree

一棵完整的、页面作用域的标签 PDF 逻辑结构树。

pub struct StructureTree {
    pub roots: Vec<StructureTreeElement>,
}

字段

名称类型文档
rootsVec<StructureTreeElement>

结构体 StructureTreeElement

一个标签 PDF 结构元素。字段名遵循本仓库的 snake_case JSON 约定,而不是 PDFium 的 C 拼写。

pub struct StructureTreeElement {
    pub element_type: String,
    pub id: Option<String>,
    pub actual_text: Option<String>,
    pub alt_text: Option<String>,
    pub title: Option<String>,
    pub attributes: std::collections::BTreeMap<String, StructureAttributeValue>,
    pub marked_content_ids: Vec<i32>,
    pub children: Vec<StructureTreeElement>,
    pub annotations: Vec<DocumentAnnotation>,
}

字段

名称类型文档
element_typeString
idOption<String>
actual_textOption<String>
alt_textOption<String>
titleOption<String>
attributesstd::collections::BTreeMap<String, StructureAttributeValue>
marked_content_idsVec<i32>
childrenVec<StructureTreeElement>
annotationsVec<DocumentAnnotation>

结构体 FormField

一个 AcroForm 控件及其解析后的字段元数据。

pub struct FormField {
    pub id: String,
    pub field_type: String,
    pub page: u32,
    pub annotation_index: i32,
    pub widget_index: i32,
    pub object_number: Option<i32>,
    pub name: Option<String>,
    pub alternate_name: Option<String>,
    pub value: Option<String>,
    pub export_value: Option<String>,
    pub field_flags: i32,
    pub control_count: Option<i32>,
    pub control_index: Option<i32>,
    pub checked: Option<bool>,
    pub rect: Option<Rect>,
    pub options: Vec<String>,
    pub selected_options: Vec<String>,
}

字段

名称类型文档
idString
field_typeString
pageu32
annotation_indexi32
widget_indexi32
object_numberOption<i32>
nameOption<String>
alternate_nameOption<String>
valueOption<String>
export_valueOption<String>
field_flagsi32
control_countOption<i32>
control_indexOption<i32>
checkedOption<bool>
rectOption<Rect>
optionsVec<String>
selected_optionsVec<String>

结构体 XfaPacket

XFA 表单文档 /XFA 数组里的一个原始数据包。启用 extract_xfa_packets 后出现在 ParseResult.xfa_packets 上。

pub struct XfaPacket {
    pub index: u32,
    pub name: Option<String>,
    pub content_length: u32,
    pub content: Option<String>,
}

字段

名称类型文档
indexu32在 XFA 数组中的下标(从 0 开始)。
nameOption<String>数据包名(例如 template、datasets),若存在。
content_lengthu32解码后的内容长度(字节)。
contentOption<String>数据包内容(通常是 XML),按 UTF-8 有损解码。无法读取该包流时为 None。

结构体 ScreenshotRect

在渲染出的页面位图里检测到的一块实心矩形(或粗线)。坐标与文字项一样处于左上原点、72 DPI 的视口坐标空间。检测跑在位图上,因此也覆盖那些没有矢量路径的扫描/压平页。

pub struct ScreenshotRect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub color: String,
    pub is_line: bool,
}

字段

名称类型文档
xf32
yf32
widthf32
heightf32
colorString填充颜色,ARGB 十六进制字符串(例如 “ff1a2b3c”)。
is_linebool当只有一个维度达到矩形最小尺寸时为 true(是一条实线而非填充区域)。

结构体 ParsedPage

表示一页完整解析后的结果,含投影后的文字版面。

与 [Page] 一样,序列化是无损的,因此 markdown 各阶段可以跑在与投影相隔一道进程边界的另一侧。公开 JSON 输出会为该类型自建自己的视图(output/json.rs)。

pub struct ParsedPage {
    pub page_number: usize,
    pub page_label: Option<String>,
    pub page_width: f32,
    pub page_height: f32,
    pub content_bounds: Option<Rect>,
    pub text: String,
    pub markdown: String,
    pub text_items: Vec<TextItem>,
    pub projected_lines: Vec<ProjectedLine>,
    pub regions: Region,
    pub graphics: Vec<GraphicPrimitive>,
    pub vector_graphics: Option<VectorGraphics>,
    pub figures: Vec<Rect>,
    pub projected_item_frames: Vec<(Rect, Rect)>,
    pub struct_nodes: Vec<StructNode>,
    pub image_refs: Vec<ImageRef>,
    pub complexity: Option<crate::ocr_merge::PageComplexityStats>,
    pub annotations: Option<Vec<DocumentAnnotation>>,
    pub form_fields: Option<Vec<FormField>>,
    pub structure_tree: Option<StructureTree>,
    pub blocks: Option<Vec<crate::layout::LayoutBlock>>,
}

字段

名称类型文档
page_numberusize
page_labelOption<String>该页对应的文档 /PageLabels 项(“iv”、“A-1”),若 PDF 定义了。它是阅读器展示给用户的页码,并不总等于页在文档中的位置;为 None 表示 PDF 未给它标签,消费方应回退到 page_number。
page_widthf32
page_heightf32
content_boundsOption<Rect>该页顶层内容对象在视口坐标下的边界框并集(可见内容范围)。空白页为 None。
textString
markdownString
text_itemsVec<TextItem>
projected_linesVec<ProjectedLine>markdown 输出器使用的逐行结构元数据。不属于公开 JSON/text 输出。
regionsRegion该页 XY-cut 区域树的根。叶子对应每条 ProjectedLine 的 region_path。仅供内部使用。
graphicsVec<GraphicPrimitive>页上的矢量图形(拆解后的路径),markdown 输出器用它检测有框表格 / 分隔线 / 图形聚簇。不属于公开 JSON/text 输出。
vector_graphicsOption<VectorGraphics>公开的矢量路径抽取。除非显式开启,否则不出现。
figuresVec<Rect>由 graphics 推导出的图形区域矩形。在 to_parsed_pages 里预先算好,供 XY-cut 版面流程把它们当作障碍物,并在下游复用于图形分类。
projected_item_framesVec<(Rect, Rect)>每个文字项的 (projected, original) 几何,只有当该页至少有一个项两者不同时才填充。为处理旋转阅读顺序,90°/270° 文字会被转正,整组也可能被挪到页面下方的虚拟画布上以便按正确顺序阅读;ProjectedLine.bbox(以及由此并集出的块框)都处于这个投影坐标系里。块/单元格框在报告前会经这张表映射回去,因此它们与 text_items 落在同一视口坐标空间。没有旋转文字的页此项为空 —— 绝大多数页面属于此类。
struct_nodesVec<StructNode>该页的结构树节点(仅标签化 PDF)。已按前序预展平。markdown 分类器用它做最高优先级的标题 / 图形 / 表格检测。
image_refsVec<ImageRef>页上的位图对象。边界框为视口坐标。在抽取阶段填充;markdown 输出器用它在正确的 y 位置插入 Block::Figure 引用。页内没有内嵌图片时为空。不属于公开 JSON/text 输出。
complexityOption<crate::ocr_merge::PageComplexityStats>逐页复杂度信号(与 is_complex API 返回的相同)。仅在设置 LiteParseConfig::include_complexity 时填充,否则为 None。在 JSON 里以每页一个 complexity 对象呈现。
annotationsOption<Vec<DocumentAnnotation>>开启 LiteParseConfig::extract_annotations 时的页面批注。None 表示未开启抽取;Some([]) 表示已开启但该页没有批注。
form_fieldsOption<Vec<FormField>>开启 extract_form_fields 时的 AcroForm 控件。
structure_treeOption<StructureTree>开启 extract_structure_tree 时的标签 PDF 逻辑结构。
blocksOption<Vec<crate::layout::LayoutBlock>>开启 extract_blocks 时按阅读顺序给出的分类版面块。None 表示未开启抽取;Some([]) 表示已开启但该页没有结构拆解(空白页,或纯 OCR 且缺少分类器所需的字体元数据)。

结构体 ExtractedImage

从页面抽取出的位图及其像素字节。只有在启用 extract_images 时才会出现在 ParseResult.images 上;否则抽取步骤跳过渲染,只产出 ImageRef。当 PDFium 暴露了可直接解码的合法 DCT 流时,JPEG 流会被原样保留而不重新编码;其他图片则由 PDFium 渲染出的位图编码为 PNG。

pub struct ExtractedImage {
    pub id: String,
    pub name: String,
    pub path: Option<String>,
    pub page: u32,
    pub bbox: Rect,
    pub width: u32,
    pub height: u32,
    pub rotation: f32,
    pub format: String,
    pub duplicate_of: Option<String>,
    pub bytes: std::sync::Arc<Vec<u8>>,
}

字段

名称类型文档
idString
nameString
pathOption<String>
pageu32
bboxRect
widthu32
heightu32
rotationf32
formatString
duplicate_ofOption<String>
bytesstd::sync::Arc<Vec<u8>>编码后的图片字节。以共享(Arc)方式持有,因此重复条目引用的是规范图片的缓冲区,而不是每次出现都复制一份。不参与序列化:图片载荷要跨边界时以文件或独立 blob 形式给出,并以 id 为键。

结构体 VectorGraphics

页面作用域的矢量路径输出。坐标与文字项一样采用左上原点、72 DPI 的视口坐标空间。

pub struct VectorGraphics {
    pub shapes: Vec<VectorShape>,
    pub lines: Vec<VectorLine>,
}

字段

名称类型文档
shapesVec<VectorShape>
linesVec<VectorLine>

结构体 VectorShape

一个 PDF 路径对象的描绘状态与视口边界框。

pub struct VectorShape {
    pub bbox: Rect,
    pub stroke: bool,
    pub stroke_color: Option<String>,
    pub fill: bool,
    pub fill_color: Option<String>,
    pub has_curve: bool,
}

字段

名称类型文档
bboxRect
strokebool
stroke_colorOption<String>
fillbool
fill_colorOption<String>
has_curvebool

结构体 VectorLine

在相邻兼容段被合并之后得到的严格水平或垂直路径段,与 LlamaParse 的 PDFium 路径语义一致。

pub struct VectorLine {
    pub x1: f32,
    pub y1: f32,
    pub x2: f32,
    pub y2: f32,
    pub stroke: bool,
    pub stroke_width: Option<f32>,
    pub stroke_color: Option<String>,
    pub fill: bool,
    pub fill_color: Option<String>,
}

字段

名称类型文档
x1f32
y1f32
x2f32
y2f32
strokebool
stroke_widthOption<f32>
stroke_colorOption<String>
fillbool
fill_colorOption<String>

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。