如何基于PHP与Symfony4按指定关键词解析拆分PDF为多个文件
Symfony 4框架下按关键词拆分PDF的实现方案
你当前使用的smalot/pdfparser仅支持PDF文本解析,不具备PDF结构编辑、拆分能力,搭配纯PHP实现的PDF操作组件即可完成需求,不需要额外安装系统层面的依赖工具。
可选用的开发库
smalot/pdfparser:你现有项目已经在用的解析库,保留即可,它支持提取文本内容、文本块坐标、所属页码信息,足够完成关键词定位工作,不需要更换解析方案。setasign/fpdi:PHP生态中稳定性最高的纯PHP PDF页面重组库,支持读取现有PDF、按页抽取内容、拼接生成新的PDF文件,完美兼容Symfony 4,通过Composer可直接安装,部署无额外权限要求。tecnickcom/tcpdf:如果需要做页内内容裁剪(即拆分边界不是整页,而是同一页内的某个区域),可以选用该库配合FPDI使用,实现非整页级别的精细拆分。
不推荐依赖pdftk、Ghostscript等外部命令行工具的方案,这类方案在容器、虚拟主机环境部署时需要额外配置执行权限,适配成本高。
具体实现逻辑
你现有代码仅提取了整页文本,没有记录关键词对应的页码位置,按以下步骤调整即可完成拆分:
- 逐页遍历PDF内容时,先匹配起始关键词(如示例中的
hello),记录第一次匹配到关键词的页码作为拆分起始点 - 从起始点之后继续遍历,匹配结束关键词(如示例中的
world),记录匹配到关键词的页码作为拆分结束点 - 调用FPDI加载原PDF文件,抽取起始点到结束点之间的所有页面,拼接生成独立的新PDF文件保存即可
- 如果需要更精细的区域拆分,不要直接调用
getText()取整页内容,改用$page->getDataTm()方法获取每个文本块的坐标、所属位置,定位到关键词的具体页内坐标后,通过FPDI的裁剪功能只保留指定区域内容。
代码改造示例
首先安装需要的依赖库:
composer require smalot/pdfparser setasign/fpdi
对应你原有extract方法的改造代码如下:
public function extract(): Response { // 原PDF文件路径 $sourcePath = 'C:\Users\lenovo\Desktop\papiers\CV\CVmolkahchaichi.pdf'; // 拆分后新PDF的保存路径 $outputPath = 'C:\Users\lenovo\Desktop\papiers\CV\keyword_extracted.pdf'; $startKeyword = 'hello'; $endKeyword = 'world'; // 第一步:定位关键词对应的页码范围 $parser = new \Smalot\PdfParser\Parser(); $sourcePdf = $parser->parseFile($sourcePath); $pages = $sourcePdf->getPages(); $startPage = null; $endPage = null; foreach ($pages as $index => $page) { // Smalot页码从0计数,FPDI页码从1计数,后续计算需要+1 $pageContent = $page->getText(); // 未记录起始页时,匹配起始关键词 if ($startPage === null && str_contains($pageContent, $startKeyword)) { $startPage = $index + 1; } // 已经找到起始页后,匹配结束关键词 if ($startPage !== null && str_contains($pageContent, $endKeyword)) { $endPage = $index + 1; break; } } // 兜底逻辑:如果没找到结束关键词,默认截取到PDF最后一页 if ($endPage === null) { $endPage = count($pages); } // 第二步:抽取指定范围页面生成新PDF $fpdi = new \setasign\Fpdi\Fpdi(); $totalPages = $fpdi->setSourceFile($sourcePath); // 逐页导入指定范围的内容 for ($pageNum = $startPage; $pageNum <= $endPage; $pageNum++) { $template = $fpdi->importPage($pageNum); $pageSize = $fpdi->getTemplateSize($template); $fpdi->AddPage($pageSize['orientation'], [$pageSize['width'], $pageSize['height']]); $fpdi->useTemplate($template); } // 保存生成的新PDF $fpdi->Output($outputPath, 'F'); return new Response('指定段落提取完成,文件保存路径:' . $outputPath); }
如果需要匹配跨页的关键词、或者需要过滤掉页面内关键词之外的无关内容,把整页文本匹配的逻辑替换为逐文本块遍历、记录坐标的逻辑即可,不需要更换核心库。
内容的提问来源于stack exchange,提问作者molyyy
相关产品推荐
相关产品推荐

