用于 Java 的高级 PDF 解析器

2022-09-02 20:52:36

我想从Java中的PDF文件中提取不同的内容:

  • 完整的可见文本
  • 图像
  • 链接

是否也可以获得以下内容?

  • 文档元标签,如标题、描述或作者
  • 只有标题
  • 输入元素(如果文档包含表单)

我不需要操作或渲染PDF文件。哪个库最适合这种目的?

更新

好的,我尝试了PDFBox:

Document luceneDocument = LucenePDFDocument.getDocument(new File(path));
Field contents = luceneDocument.getField("contents");
System.out.println(contents.stringValue());

但输出为空。不过,字段“摘要”是可以的。

下一个代码段工作正常。

PDDocument doc = PDDocument.load(path);
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(doc);
System.out.println(text);
doc.close();

但是,我不知道如何提取图像,链接等。

更新 2

我找到了一个如何提取图像的示例,但我仍然没有关于如何提取的答案:

  • 链接
  • 文档元标签,如标题、描述或作者
  • 只有标题
  • 输入元素(如果文档包含表单)

答案 1

iText是我这些天来选择的PDF工具。

  • 完整的可见文本

“可见”是一个艰难的问题。您可以使用com.itextpdf.text.pdf.parse包的类来解析所有可解析的文本...但是这些类不知道剪辑。您可以轻松地将解析器限制为页面大小。

// all text on the page, regardless of position
PdfTextExtractor.getTextFromPage(reader, pageNum);

您实际上需要采用TextExtractionStrategy(过滤策略)的覆盖。它很快就会变得有趣,但我认为你可以在这里“开箱即用”获得你想要的一切。

  • 图像

是的,通过相同的包类。图像侦听器不像文本侦听器那样得到很好的支持,但确实存在。

  • 链接

是的。链接是指向各种PDF页面的“注释”。找到它们很简单,只需循环浏览每个页面的“注释数组”并挑选出链接注释即可。

PdfDictionary pageDict = myReader.getPageN(1);
PdfArray annots = pageDict.getAsArray(PdfName.ANNOTS);
ArrayList<String> dests = new ArrayList<String>();
if (annots != null) {
  for (int i = 0; i < annots.size(); ++i) {
    PdfDictionary annotDict = annots.getAsDict(i);
    PdfName subType = annotDict.getAsName(PdfName.SUBTYPE);
    if (subType != null && PdfName.LINK.equals(subType)) {
      PdfDictionary action = annotDict.getAsDict(PdfName.A);
      if (action != null && PdfName.URI.equals(action.getAsName(PdfName.S)) {
        dests.add(action.getAsString(PdfName.URI).toString());
      } // else { its an internal link, meh }
    }
  }
}

您可以在此处找到 PDF 规范

  • 输入元素

绝对。对于XFA(LiveCycle Designer)或较旧的“AcroForm”表单,iText可以找到所有字段及其值。

AcroFields fields = myReader.getAcroFields();

Set<String> fieldNames = fields.getFields().keySet();
for (String fldName : fieldNames) {
  System.out.println( fldName + ": " + fields.getField( fldName ) );
}

多选列表不会得到那么好的处理。您将在冒号后为空文本字段和按钮获得一个空格。没有太多的信息...但这会让你开始。

  • 文档元标签,如标题、描述或作者

非常琐碎。是的。

Map<String, String> info = myPdfReader.getInfo();
System.out.println( info );

除了基本的作者/标题/等之外,您还可以通过 访问一个相当复杂的 XML 架构。reader.getMetadata()

  • 只有标题

A 可以根据您希望的任何条件忽略文本。字体大小听起来是正确的,基于您的评论。TextRenderFilter


推荐