乐于分享
好东西不私藏

一个快速、实用、开源的 PHP 文档解析器

一个快速、实用、开源的 PHP 文档解析器

简介

Parsel 为 PHP 提供了一个 API,用于解析 PDF、Office 文档和图片。您的文档在本地处理,无需将文件发送到外部服务,即可提取纯文本、结构化页面数据、坐标以及截图。

Parsel 可以返回纯文本、结构化文档数据、页面截图,或者针对大型文档逐页返回。它设计为在 PHP 应用程序中使用起来自然流畅,同时在需要时仍能提供高级解析器选项。

示例代码

useShipfastlabs\Parsel;$text = Parsel::file('invoice.pdf')->text();$document = Parsel::file('invoice.pdf')    ->pageRange(15)    ->withOcr(language: 'eng')    ->withDpi(300)    ->parse();foreach ($document->pages as $page) {foreach ($page->items as $item) {echo"{$item->text} @ ({$item->x}, {$item->y})\n";    }}

Parsel 需要 PHP 8.4 或更高版本 以及 lit 二进制文件。

安装

通过 Composer 安装 Parsel:

composer require shipfastlabs/parsel

安装所需的 lit 二进制文件:

vendor/bin/parsel-install-lit

对于 Office 文档、电子表格、演示文稿和图片,您还可以安装系统依赖:

vendor/bin/parsel-install-lit --with-system-dependencies

您可以选择用于安装 lit 二进制文件的包管理器:

vendor/bin/parsel-install-lit --manager=npmvendor/bin/parsel-install-lit --manager=pnpmvendor/bin/parsel-install-lit --manager=bunvendor/bin/parsel-install-lit --manager=pipvendor/bin/parsel-install-lit --manager=cargo

您也可以自行安装 lit(以下任一命令):

cargo install liteparsepip install liteparsenpm i -g @llamaindex/liteparsepnpm add -g @llamaindex/liteparsebun add -g @llamaindex/liteparse

如果您想自行安装系统依赖,请根据您的平台使用对应命令:

macOS

brew install --cask libreoffice    # 用于 Office 文档brew install imagemagick           # 用于图片

Ubuntu / Debian

apt-get install libreoffice        # 用于 Office 文档apt-get install imagemagick        # 用于图片

Windows

choco install libreoffice-fresh    # 用于 Office 文档choco install imagemagick.app      # 用于图片

说明:LibreOffice 用于 Office 文档转换,ImageMagick 用于图片转换,OCR 支持通过 liteparse 使用 Tesseract。

解析文件

file 方法为磁盘上已存在的文档创建一个解析器实例。选择源文件后,您可以决定以何种方式返回解析结果。

useShipfastlabs\Parsel;$text = Parsel::file('/path/to/report.pdf')->text();

您也可以解析原始字节。这在处理上传文件、数据库 Blob 或未保存到磁盘的文档时非常有用。由于字节源不包含文件名,您需要提供文件扩展名。

$document = Parsel::bytes($uploadedBytes, 'pdf')->parse();

Parsel 支持 PDF、Word 文档、电子表格、演示文稿和图片。每种支持的文件类型都使用相同的流畅 API:

$text = Parsel::file('contract.docx')->text();$rows = Parsel::file('report.xlsx')->text();$slides = Parsel::file('deck.pptx')->text();$scan = Parsel::file('receipt.png')    ->withOcr()    ->text();$photo = Parsel::file('invoice.jpg')    ->withOcr(language: 'eng')    ->parse();

纯文本输出

text 方法以字符串形式返回解析后的文档文本。Parsel 在返回前会移除文本输出中的页眉标记。

$text = Parsel::file('document.pdf')    ->withoutOcr()    ->text();

结构化文档

parse 方法返回一个 Document 对象,包含文档文本、元数据、页面以及带位置信息的文本项。当您需要坐标、字体信息或 OCR 置信度时非常有用。

$document = Parsel::file('document.pdf')->parse();echo $document->text;echo $document->pageCount();foreach ($document->pages as $page) {foreach ($page->items as $item) {echo $item->text;    }}

文档也可以作为数组返回:

$array = Parsel::file('document.pdf')->toArray();

页面选择

pagepages 和 pageRange 方法可用于限制仅解析特定页面。这些方法是累加的,您可以在解析文档前多次调用它们。

Parsel::file('document.pdf')->page(7);Parsel::file('document.pdf')->pages(135);Parsel::file('document.pdf')->pages('1-5'10);Parsel::file('document.pdf')->pageRange(15);Parsel::file('document.pdf')->pageRange(15)->page(10);

如果只需限制解析的页面数量,可使用 maxPages 方法:

Parsel::file('document.pdf')->maxPages(50)->text();

OCR

默认情况下 OCR 被禁用,以保持解析速度快且可预测。您可以使用 withOcr 方法启用 OCR:

$text = Parsel::file('scan.pdf')->withOcr()->text();

withOcr 方法接受命名参数来设置常用 OCR 选项:

$text = Parsel::file('scan.pdf')    ->withOcr(        language: 'fra',        tessdataPath: '/usr/share/tessdata',        serverUrl: 'http://localhost:8828/ocr',        workers: 8,    )    ->text();

如果您想明确禁用 OCR,可以调用 withoutOcr

$text = Parsel::file('document.pdf')->withoutOcr()->text();

渲染选项

Parsel 提供了便捷方法来设置常用解析器选项,例如渲染 DPI、保留小文本、加密文档以及每次调用的进程设置。

Parsel::file('document.pdf')->withDpi(300);Parsel::file('document.pdf')->preserveSmallText();Parsel::file('secret.pdf')->withPassword('hunter2');Parsel::file('document.pdf')->withBinary('/usr/local/bin/lit');Parsel::file('document.pdf')->withTimeout(120);

附加选项

如果需要传递 Parsel 尚未提供专用方法的标志,可以使用 option 方法直接传递。布尔选项无需值,需要值的选项可作为第二个参数传入。

Parsel::file('document.pdf')->option('some-new-flag');Parsel::file('document.pdf')->option('some-new-flag'42);

保存输出

save 方法将解析结果写入磁盘并返回写入的路径。如果目标路径以 .json 结尾,Parsel 将写入 JSON;其他扩展名则写入纯文本。

Parsel::file('document.pdf')->save('document.txt');Parsel::file('document.pdf')->save('document.json');

截图

您可以使用 screenshots 方法将页面截图渲染到指定目录。该方法在解析完成后返回输出目录中的图像文件。

$screenshots = Parsel::file('document.pdf')    ->pageRange(15)    ->screenshots('/tmp/parsel-pages');

为获得可预测的结果,应传入一个专用的、不包含无关文件的输出目录。

流式处理大型文档

parse 和 toArray 方法会将整个文档加载到内存中。对于大型文档,您可以使用 lazyPages 逐页处理。

foreach (Parsel::file('large-document.pdf')->lazyPages() as $page) {foreach ($page->items as $item) {// 逐页处理...    }}

这允许 Parsel 增量读取页面,而无需将整个文档保存在内存中。

文档数据结构

解析后的 Document 包含完整文本、元数据和页面列表。每页包含尺寸、页面文本以及带位置数据的文本项。

$document->text;$document->metadata;$document->pages;$document->pageCount();$page->number;$page->width;$page->height;$page->text;$page->items;$item->text;$item->x;$item->y;$item->width;$item->height;$item->fontName;$item->fontSize;$item->confidence;

二进制文件解析顺序

Parsel 需要解析文档时,按以下顺序查找 lit 二进制文件:

  1. 通过 withBinary 配置的单次调用二进制文件。
  2. 通过 Parsel::usingBinary 配置的全局二进制文件。
  3. PARSEL_LIT_BINARY 环境变量。
  4. 系统 PATH 中的 lit 二进制文件。

如果无法找到二进制文件,Parsel 将抛出 BinaryNotFoundException

Parsel::usingBinary('/usr/local/bin/lit');Parsel::defaultTimeout(120);

测试

Parsel 包含一个模拟运行器,允许您的测试在不启动真实二进制文件的情况下测试解析代码。响应键作为子字符串与命令行匹配。当多个响应匹配时,使用最长的匹配键。

useShipfastlabs\Parsel;$fake = Parsel::fake(['--format json' => file_get_contents(__DIR__.'/fixtures/lit-output.json'),]);$document = Parsel::file('invoice.pdf')->parse();expect($fake->recordedCommands()[0])->toContain('--format''json');

字符串响应作为成功的 stdout 返回。如果需要控制退出码或 stderr,可以提供 ProcessResult 实例。

开发

Parsel 使用 Pint、Rector、PHPStan 和 Pest 来保持代码格式化和充分测试。

composer lintcomposer test:typescomposer test:unitcomposer test

集成测试针对真实解析器安装运行,当 lit 二进制文件不可用时会跳过:

./vendor/bin/pest --group=integration