Adobe Acrobat JavaScript:检测含下划线/删除线文本的PDF页面并提取至新文档的实现方法
Adobe Acrobat JavaScript:检测含下划线/删除线文本的PDF页面并提取至新文档的实现方法
你遇到的问题其实是Acrobat JavaScript API的一个常见限制——getPageNthWord()确实只会返回纯文本字符串,完全不带任何样式属性,所以你代码里尝试访问.style.strikeThru或者.underline肯定会报错,因为字符串根本没有这些属性。
之所以会这样,是因为PDF里的下划线、删除线这类装饰,很多时候并不是作为文本的“属性”存储的,而是单独绘制的图形线条(比如一条细横线),和文本内容是分离的元素。Acrobat的基础文本提取接口并没有把这些图形和对应的文本关联起来,所以没法直接通过文本对象获取样式信息。
可行的实现思路
要实现你的需求,得换个思路:我们可以先获取页面上所有文本的位置,再检查页面上是否有和这些文本位置重叠的、符合下划线/删除线特征的图形元素。同时先修正你代码里的一些基础错误(比如重复添加页面、插入参数错误),下面是改进后的代码框架:
var pageSet = new Set(); // 用Set避免重复添加同一页面 for (var p = 0; p < this.numPages; p++) { var hasStyledText = false; var wordCount = this.getPageNumWords(p); // 遍历页面所有单词,获取它们的位置边界 for (var n = 0; n < wordCount; n++) { var wordQuads = this.getPageNthWordQuads(p, n); if (!wordQuads || wordQuads.length === 0) continue; // 提取单词的坐标边界(单个单词通常对应一个四边形) var quad = wordQuads[0]; var wordLeft = Math.min(quad[0], quad[2], quad[4], quad[6]); var wordRight = Math.max(quad[0], quad[2], quad[4], quad[6]); var wordTop = Math.max(quad[1], quad[3], quad[5], quad[7]); var wordBottom = Math.min(quad[1], quad[3], quad[5], quad[7]); var wordHeight = wordTop - wordBottom; // 解析页面内容流,查找符合特征的水平线条 var pageContent = this.getPageContent(p); var linePattern = /(\d+\.?\d*) (\d+\.?\d*) m (\d+\.?\d*) (\d+\.?\d*) l S/g; var match; while ((match = linePattern.exec(pageContent)) !== null) { var x1 = parseFloat(match[1]), y1 = parseFloat(match[2]); var x2 = parseFloat(match[3]), y2 = parseFloat(match[4]); // 判断是否是近似水平的线条(y坐标差异极小) if (Math.abs(y1 - y2) < 0.5) { var lineLeft = Math.min(x1, x2); var lineRight = Math.max(x1, x2); var lineY = y1; // 判断是否为下划线(线条在文本下方,距离不超过单词高度1/3) var isUnderline = (lineY > wordBottom - wordHeight/3) && (lineY < wordBottom); // 判断是否为删除线(线条在文本垂直中间区域) var isStrikeThru = (lineY > wordBottom + wordHeight/3) && (lineY < wordTop - wordHeight/3); // 判断线条和单词的水平范围是否重叠 var isOverlap = (lineRight > wordLeft) && (lineLeft < wordRight); if ((isUnderline || isStrikeThru) && isOverlap) { hasStyledText = true; break; } } } if (hasStyledText) break; } if (hasStyledText) { pageSet.add(p); } } var pageArray = Array.from(pageSet); if (pageArray.length > 0) { var d = app.newDoc(); // 修正插入页面的参数:nStart和nEnd要取单个页码 for (var n = 0; n < pageArray.length; n++) { var pageNum = pageArray[n]; d.insertPages({ nPage: d.numPages - 1, cPath: this.path, nStart: pageNum, nEnd: pageNum, }); } // 删除初始的空白页 d.deletePages(0); }
补充说明
上面的内容流解析是简化版逻辑,实际PDF的内容流可能更复杂(比如包含矩阵变换、不同的线条绘制命令),如果要覆盖更多场景,你需要更完整的PDF内容流解析逻辑。另外,有些PDF的下划线是字体本身的一部分(比如内置下划线的字形),这种情况用上述方法无法检测,需要结合字体信息判断,难度会更高。
你提到有人说这在Adobe里不可能,其实也不完全对——只是没有直接的API方法,需要通过间接的图形检测来实现,不过确实存在不少边缘情况可能导致检测不准确。
备注:内容来源于stack exchange,提问作者Andrew Rehn
相关产品推荐
相关产品推荐

