使用PDF.js能否提取PDF页数、图片及alt文本、表格、交互元素等信息?
PDF元素统计需求实现方案
你的需求完全可以通过PDF.js实现,针对你提到的问题,具体实现方法如下:
各指标统计逻辑
- 总页数:直接读取
doc.numPages属性即可,你当前的实现已经覆盖该需求 - 图片总数量:遍历页面操作符列表时,匹配
pdfJS.OPS.paintImageXObject操作码,出现一次即计数一张图片,汇总所有页面的计数即可得到总图片量 - 图片alt文本:alt文本存储在PDF结构树(标签树)中,而非普通操作符参数里。调用
await page.getStructTree()获取页面结构树后,遍历所有类型为Figure的节点,节点的alt属性即为对应图片的alt文本,无该属性则说明图片未设置alt - 表格数量:带标签的PDF可直接在结构树中统计类型为
Table的节点数量;无标签的PDF需要额外做边框、文本排版识别,复杂度较高 - 交互元素数量:调用
await page.getAnnotations()获取页面所有注释,按类型过滤即可:Link类型对应超链接,Widget类型对应表单控件等交互元素,汇总对应类型的数量即可
现有代码问题修复
你当前的代码存在两个核心问题:
- 使用
Array.from包裹异步函数时没有用Promise.all等待所有页面处理完成,会导致提前返回结果时数据不全 - 仅遍历了操作符参数,未获取结构树,因此无法定位alt文本
以下是修复后的核心代码示例:
const pdfJS = require('pdfjs-dist'); // 若为浏览器环境引入对应umd包即可 async function analyzePdf(buffer) { const result = { pageCount: 0, imageCount: 0, imageWithAltCount: 0, tableCount: 0, interactiveElementCount: 0 }; const doc = await pdfJS.getDocument({ data: buffer }).promise; result.pageCount = doc.numPages; // 等待所有页面处理完成 await Promise.all(Array.from({ length: doc.numPages }, async (_, idx) => { const page = await doc.getPage(idx + 1); // 统计图片数量 const ops = await page.getOperatorList(); for (let i = 0; i < ops.fnArray.length; i++) { if (ops.fnArray[i] === pdfJS.OPS.paintImageXObject) { result.imageCount++; } } // 统计图片alt、表格数量 const structTree = await page.getStructTree(); const traverseStruct = (node) => { if (node.type === 'Figure') { if (node.alt) result.imageWithAltCount++; } if (node.type === 'Table') { result.tableCount++; } if (node.children) node.children.forEach(traverseStruct); }; traverseStruct(structTree); // 统计交互元素 const annotations = await page.getAnnotations(); result.interactiveElementCount += annotations.filter(anno => anno.subtype === 'Link' || anno.subtype === 'Widget' ).length; })); return result; }
备选工具方案
如果遇到PDF.js处理异常的边界场景,可根据运行环境选择其他工具:
- Node.js服务端场景可以用
pdf-lib,直接读取PDF底层结构字典,提取标签和元素信息的灵活性更高,也直接支持buffer输入 - 本地Node.js环境也可以使用Poppler的Node绑定,配合
pdftotext的标签导出能力,也能拿到完整的PDF元素信息
内容的提问来源于stack exchange,提问作者Gavin Coulson
相关产品推荐
相关产品推荐

