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

如何使用PDFBox解析含键值对结构的PDF文件?

嘿,你已经用PDFLayoutTextStripper搞定了格式良好的文本提取,这步走得很稳!接下来要解析那些someKey1 someValue1这类键值对,我给你几个实用的方案,你可以根据自己PDF的实际格式来选:

方案1:简单字符串分割(适合键值对格式固定的场景)

如果你的键值对是键和值用空格分隔,而且每行一个键值对,直接对提取到的文本做分割就够了。要是值里可能包含空格,记得用split(" ", 2)只拆分第一个空格,避免把值拆碎:

// 承接你已有的代码,拿到text之后
Map<String, String> keyValueMap = new HashMap<>();
String[] lines = text.split("\\n"); // 按行分割文本

for (String line : lines) {
    String[] keyValueParts = line.split(" ", 2); // 只拆分成键、值两部分
    if (keyValueParts.length == 2) {
        String key = keyValueParts[0].trim();
        String value = keyValueParts[1].trim();
        // 可以加个过滤,只处理符合命名规则的键(比如以someKey开头)
        if (key.startsWith("someKey")) {
            keyValueMap.put(key, value);
        }
    }
}

// 打印解析结果
keyValueMap.forEach((k, v) -> System.out.println(k + ": " + v));
方案2:正则表达式匹配(应对更灵活的格式)

如果键值对可能夹杂在其他文本里,或者键的命名有更复杂的规律(比如someKey后面跟数字),正则表达式会更靠谱。下面这个正则能匹配someKey+数字格式的键,自动捕获后面的对应值,直到遇到下一个键或者文本结尾:

// 承接已有的text字符串
Map<String, String> keyValueMap = new HashMap<>();
Pattern keyValuePattern = Pattern.compile("(someKey\\d+)\\s+(.*?)(?=\\s+someKey|\\Z)");
Matcher matcher = keyValuePattern.matcher(text);

while (matcher.find()) {
    String key = matcher.group(1).trim();
    String value = matcher.group(2).trim();
    keyValueMap.put(key, value);
}

// 输出结果
keyValueMap.forEach((k, v) -> System.out.println(k + ": " + v));

简单解释下这个正则:

  • (someKey\\d+):捕获以someKey开头、后面跟数字的键
  • \\s+:匹配键和值之间的空格
  • (.*?):非贪婪匹配值的内容,直到遇到下一个someKey或者文本结束
方案3:结合文本位置信息(应对排版复杂的PDF)

如果你的PDF里键值对不是同一行,比如键在上行、值在下行,或者分栏排版,光靠字符串就不够准了。这时候可以自定义PDFTextStripper子类来获取每个文本片段的坐标,再根据位置关联键和值:

// 自定义TextStripper,用来捕获每个文本的位置信息
class PositionAwareTextStripper extends PDFTextStripper {
    private final List<TextPosition> allTextPositions = new ArrayList<>();

    public PositionAwareTextStripper() throws IOException {
        super();
    }

    @Override
    protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
        allTextPositions.addAll(textPositions);
        super.writeString(text, textPositions);
    }

    public List<TextPosition> getAllTextPositions() {
        return allTextPositions;
    }
}

然后在你的主代码里使用这个类:

File f = new File("myFile.pdf");
PDDocument doc = PDDocument.load(f);

PositionAwareTextStripper stripper = new PositionAwareTextStripper();
stripper.getText(doc); // 触发文本提取,同时捕获位置信息
List<TextPosition> textPositions = stripper.getAllTextPositions();

Map<String, String> keyValueMap = new HashMap<>();
String currentKey = null;
float lastKeyY = 0;

for (TextPosition tp : textPositions) {
    String text = tp.getUnicode().trim();
    if (text.startsWith("someKey")) {
        currentKey = text;
        lastKeyY = tp.getY(); // 记录当前键的y坐标
    } else if (currentKey != null) {
        // 这里根据实际排版调整位置判断逻辑,比如值和键的y坐标接近,x坐标更大
        if (Math.abs(tp.getY() - lastKeyY) < 5) { // 假设y坐标差小于5就算同一行
            keyValueMap.put(currentKey, text);
            currentKey = null;
        }
    }
}

doc.close();

这个方法需要你根据PDF的实际排版来调整坐标判断的阈值,比如y坐标差多少算同一行,x坐标多少算键的右侧值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:31:07