You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用iText提取PDF文档中的各级标题?

用iText提取PDF层级标题的实现思路

嘿,我来给你梳理几个用iText提取PDF层级标题的可行思路,结合你现有的代码展开说说:

思路一:基于文本格式特征识别标题

标题通常有明显的格式特征——比如更大的字号、加粗样式、特定颜色,或者固定的缩进位置。你当前用的SimpleTextExtractionStrategy只能提取纯文本,没法获取格式信息,所以可以换成自定义的文本提取策略,通过TextRenderInfo获取每个文本块的字体、字号、位置等属性,再筛选出符合标题特征的内容,最后根据格式差异区分层级(比如一级标题字号最大,二级次之)。

示例代码(适配iText 5):

// 自定义策略,检测带格式特征的标题
class HeadingDetectionStrategy extends LocationTextExtractionStrategy {
    @Override
    public void renderText(TextRenderInfo renderInfo) {
        // 获取文本块的字号
        float fontSize = renderInfo.getFontSize();
        // 判断是否为加粗字体(通过字体名称识别,不同字体命名可能有差异)
        boolean isBold = renderInfo.getFont().getFontName().contains("Bold");
        String text = renderInfo.getText().trim();

        // 自定义规则:比如字号>14且加粗,同时文本不为空
        if (fontSize > 14 && isBold && !text.isEmpty()) {
            // 这里可以进一步根据Y轴位置(标题通常在页面上方)或缩进判断层级
            System.out.println("疑似一级标题:" + text);
        } else if (fontSize > 12 && isBold && !text.isEmpty()) {
            System.out.println("疑似二级标题:" + text);
        }
        super.renderText(renderInfo);
    }
}

// 在你的循环中替换为自定义策略
for(int i = 1; i <= pdfReader.getNumberOfPages(); i++){ 
    HeadingDetectionStrategy headingStrategy = new HeadingDetectionStrategy();
    parser.processContent(i, headingStrategy);
}

思路二:利用Tagged PDF的结构树提取(最准确)

如果你的目标PDF是带标签的PDF(Tagged PDF),文档内部会定义Heading1、Heading2这类结构化元素,直接读取结构树就能精准获取标题和层级,不需要依赖格式猜测。iText提供了遍历结构树的API,能直接定位到标题节点。

示例代码(适配iText 5):

PdfDocument pdfDoc = new PdfDocument(pdfReader);
PdfStructTreeController structTreeController = new PdfStructTreeController(pdfDoc);
PdfStructElem rootElem = structTreeController.getRoot();

// 递归遍历结构树,提取标题
traverseStructElements(rootElem, 1);

// 递归处理结构元素的方法
private void traverseStructElements(PdfStructElem elem, int level) {
    if (elem == null) return;
    // 获取元素的角色(比如Head1、Head2,不同PDF的命名可能略有不同)
    PdfName role = elem.getRole();
    if (PdfName.Head1.equals(role) || role.toString().startsWith("Head")) {
        // 提取标题文本
        String headingText = PdfTextExtractor.getTextFromElement(elem);
        System.out.println("层级" + level + "标题:" + headingText);
    }
    // 遍历子元素,层级+1
    for (PdfObject kid : elem.getKids()) {
        if (kid instanceof PdfStructElem) {
            traverseStructElements((PdfStructElem) kid, level + 1);
        }
    }
}

注意:这个方法仅适用于带标签的PDF,普通无标签PDF无法使用。

思路三:基于标题编号规则识别

如果你的PDF标题都遵循类似1、1.1、1.2.1的编号规则,可以先提取页面纯文本,再用正则表达式匹配符合编号格式的行,通过编号中点的数量判断层级(比如1是1级,1.1是2级,1.2.1是3级)。

示例代码:

for(int i = 1; i <= pdfReader.getNumberOfPages(); i++){ 
    TextExtractionStrategy strategy = parser.processContent(i, new SimpleTextExtractionStrategy()); 
    String pageText = strategy.getResultantText();
    // 按行分割文本(注意有些PDF换行符是\n或\r\n,需根据实际调整)
    String[] lines = pageText.split("\\r?\\n");
    // 匹配编号开头的标题:数字+可选的.数字,后面跟空格和标题文本
    Pattern headingPattern = Pattern.compile("^(\\d+(\\.\\d+)*)\\s+(.+)");
    
    for (String line : lines) {
        String trimmedLine = line.trim();
        Matcher matcher = headingPattern.matcher(trimmedLine);
        if (matcher.find()) {
            String numbering = matcher.group(1);
            String titleContent = matcher.group(3);
            // 计算层级:编号中点的数量+1
            int level = numbering.split("\\.").length;
            System.out.println("层级" + level + "标题:" + titleContent);
        }
    }
}

这个方法的优势是不需要依赖格式,只要编号规范就能识别,但如果标题没有编号或者编号不统一,效果会大打折扣。


内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:05:42