PDF-OCR文件识别篇(三):PDF 切分与表格还原 为什么先讲切分因为「按表」是整条流水线的最小处理单元。一份 PDF 可能有几十张表只有先把它拆成一张一张后面的并行抽取、单表重试、按表注入字段定义才有可能。本章对应包com.example.pdfextraction.pdf。3.1 按表切分PdfTableSlicer逐页用 PDFBox 提取文本识别行首形如「表1 …」的标题把文档切成若干PdfSection。Component public class PdfTableSlicer { // 表格标题行首「表 数字」例如「表1 ...」「表 12 ...」 private static final Pattern TABLE_TITLE Pattern.compile(^\\s*表\\s*\\d\\b.*); public ListPdfSection slice(byte[] pdfBytes) { try (PDDocument document PDDocument.load(pdfBytes)) { PDFTextStripper stripper new PDFTextStripper(); stripper.setSortByPosition(true); // 按坐标排序减少跨栏错乱 // ① 先逐页抽取文本 ListString pageTexts 每页 stripper.getText(document); // ② 收集所有「表N」标题出现位置按归一化标题去重 // ③ 由相邻标题确定每段页范围 } } }三个关键处理每一个都对应一类真实坑跨页标题去重。跨页表的标题会在每页顶部重复出现。若不处理同一张表会被切成多段。做法是把标题「去表号 去空白」归一化成 key用Set.add(key)只保留首次出现String key normalizeTitle(t); // 去「表N」前缀与空白 if (StringUtils.isEmpty(key) || !seen.add(key)) continue; // 已见过则跳过边界页共享。下一张表的标题页往往同时印着上一张表的尾部跨页表尾与下表标题同页。所以相邻两段共享这个边界页都包含进去避免漏掉落在该页上半部的尾部数据end (i 1 titles.size()) ? titlePages.get(i 1) : pages; // 截到下一个标题页(含)可配置大标题切分。除了「表N」有些章节没有表号但也要单独成段如「补充说明」。通过pdf.ai.split-headings配关键词isConfiguredHeading去掉可选序号前缀「八、」「9.」后按关键词匹配 最终可获取到 八、补充说明 大标题下内容。本人测试分割文件格式为表1 xxxxxx表表2xxxxx表八、补充登记信息九、xxxxx信息private static final Pattern HEADING_NUM_PREFIX Pattern.compile(^[一二三四五六七八九十百零\\d][、.]\\s*); private static final int BIG_HEADING_MAX_LEN 60; // 行太长视为正文避免误判切出的每个PdfSection持有title // 表格标题 startPage // 起始页 endPage // 结束页 text // 整段合并文本 pageTexts // 逐页文本供按页分块时附「表头参考」用3.2 单表导出PdfSplitter当走「文件抽取」路径useFiletrue把单张表 PDF 直接上传给模型让它先解析时需要把单张表的页范围导出成独立 PDF。用 PDFBoximportPage实现落到临时文件用完即删public String splitToTempPdf(byte[] pdfBytes, int start, int end) { try (PDDocument src PDDocument.load(pdfBytes); PDDocument out new PDDocument()) { int s Math.max(1, start), e Math.min(src.getNumberOfPages(), end); for (int p s; p e; p) out.importPage(src.getPage(p - 1)); File tmp File.createTempFile(ai-table-, .pdf); out.save(tmp); return tmp.getAbsolutePath(); } } // 调用方在 finally 里 Files.deleteIfExists(tmpPath) 清理3.4 小结类输入输出用在哪PdfTableSlicerPDF 字节ListPdfSection按表切段所有路径的第一步PdfSplitterPDF 页范围单表临时 PDF 路径文件抽取路径由于pdf会出现大文件某个表格就几十近百行。如果一整个文件去执行显然不合适的。故以异步思想将互不相关的表格和特殊表头对应的数据进行分割也提高执行效率、准确率。如果你也面临同样的需求将本文章交给aiai会给详细的解释。这里仅提供实现思想。