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

使用iTextPDF的TextRegionEventFilter提取文本时出现单字符返回问题

iTextPDF解析LinkedIn简历PDF时的单字符提取问题及调试方案

我在开发LinkedIn生成PDF的简历解析器时遇到iTextPDF相关问题:

之前用SimpleTextExtractionStrategy可以完整提取文本并按行分割,顺序和PDF内一致,代码如下:

public String getNameAndSurname(PdfDocument pdfDoc) {
        SimpleTextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
        PdfCanvasProcessor proc = new PdfCanvasProcessor(strategy);
        proc.processPageContent(pdfDoc.getFirstPage());
        System.out.println(strategy.getResultantText());
        return strategy.getResultantText().split(System.lineSeparator())[0];
    }

但为了按行拆分教育、经历等简历区块,我自定义了继承TextRegionEventFilter的过滤器,大部分功能正常,但部分场景下提取的内容是单个字符(已确认目标行无特殊符号),尝试拼接字符但找不到规律,过滤器代码如下:

@Override
public boolean accept(IEventData data, EventType type) {
    if (type.equals(EventType.RENDER_TEXT)) {
        TextRenderInfo renderInfo = (TextRenderInfo) data;
            if (
                    setBlock(renderInfo, BLOCK_START, BLOCK_END) &&
                    isFontMatch(renderInfo, LINE_FONT_NAME, LINE_FONT_SIZE)
            ) {
                super.elements.add(renderInfo.getText());
                return true;
            }
        }
    return false;
}

我试过把页面尺寸从文档获取改成直接设为PageSize.A4,问题依旧。当前输出示例:

{
        "jobRole": "T",
        "company": "Company 4",
        "timePeriod": "XXX 2017 - XXX 2017 (3 months)"
    },
    {
        "jobRole": "r",
        "company": "Company 3",
        "timePeriod": "XXX 2016 - XXX 2016 (9 months)"
    },
    {
        "jobRole": "a",
        "company": "Company2",
        "timePeriod": "XXX 2014 - XXX 2015 (10 months)"
    },
    {
        "jobRole": "i",
        "company": "Company1",
        "timePeriod": "XXX 2014 - XXX 2014 (7 months)"
    }

问题分析与调试建议

这大概率不是iTextPDF的Bug,而是LinkedIn生成PDF时的文本渲染特性导致的:

  • 检查文本渲染单元:LinkedIn的PDF可能会把同一行的文字拆成多个独立的TextRenderInfo对象(比如每个字母单独渲染),你的过滤器每次只取单个renderInfo.getText(),自然会得到单字符。可以在accept方法里打印每个renderInfo的文本、位置、字体信息,确认是否存在这种拆分。
  • 验证区域过滤逻辑:setBlock方法可能误判了文本的区域范围,只捕获到了单个字符所在的区域。可以输出renderInfo.getBaseline().getBoundingRectangle()的坐标,对比预期的区块范围,看是否存在区域匹配偏差。
  • 字体匹配逻辑排查:isFontMatch方法的判断条件可能过于严格,比如字体名大小写、字号精度(比如实际是11.99而你判断12),导致只有单个字符的字体符合条件。可以打印renderInfo.getFont().getFontProgram().getFontNames().getFontName()和renderInfo.getFontSize(),核对匹配规则。
  • 参考SimpleTextExtractionStrategy的拼接逻辑:该策略内部会根据文本的位置(比如基线是否连续、间距是否正常)来拼接字符,你可以参考它的源码,在过滤器里实现类似的字符拼接逻辑,而不是直接添加单个renderInfo的文本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:32:05