一个快速、实用、开源的 PHP 文档解析器
简介
Parsel 为 PHP 提供了一个 API,用于解析 PDF、Office 文档和图片。您的文档在本地处理,无需将文件发送到外部服务,即可提取纯文本、结构化页面数据、坐标以及截图。
Parsel 可以返回纯文本、结构化文档数据、页面截图,或者针对大型文档逐页返回。它设计为在 PHP 应用程序中使用起来自然流畅,同时在需要时仍能提供高级解析器选项。
示例代码
useShipfastlabs\Parsel;$text = Parsel::file('invoice.pdf')->text();$document = Parsel::file('invoice.pdf') ->pageRange(1, 5) ->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();
页面选择
page、pages 和 pageRange 方法可用于限制仅解析特定页面。这些方法是累加的,您可以在解析文档前多次调用它们。
Parsel::file('document.pdf')->page(7);Parsel::file('document.pdf')->pages(1, 3, 5);Parsel::file('document.pdf')->pages('1-5', 10);Parsel::file('document.pdf')->pageRange(1, 5);Parsel::file('document.pdf')->pageRange(1, 5)->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(1, 5) ->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 二进制文件:
-
通过 withBinary配置的单次调用二进制文件。 -
通过 Parsel::usingBinary配置的全局二进制文件。 -
PARSEL_LIT_BINARY环境变量。 -
系统 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
夜雨聆风