【问题标题】:Extract Text from PDF Column wise, with column varying in size and position从 PDF 列中提取文本,列的大小和位置不同
【发布时间】:2019-07-12 21:00:40
【问题描述】:

如何从按列分隔的 PDF 文件中提取文本,以使结果由这些列分隔?

这些列可以有不同的高度,并且有时可以跨越多个页面。

下面是示例 PDF 的图片。这就是我需要阅读文本的方式。

两条黑线之间的每个部分都是一个组。 在每一组中, 第一列可以跨越多行 第二列和第三列在每一行都是相关的。

我尝试了以下链接提出的解决方案。 extract PDF text by columns 但运气不好。

任何帮助将不胜感激。

pdf 可在以下链接中找到。 Sample PDF

【问题讨论】:

  • 您的 pdf 文件被标记了吗?标记已经变得越来越普遍,带有标记的文本提取可能会很好地保持结构。
  • @mkl 他们没有被标记。
  • 你能分享一个PDF示例吗?
  • @mkl 我在问题中提供了示例 PDF。您可以从那里下载。

标签: pdf itext pdfbox pdftotext


【解决方案1】:

您的问题没有提到您选择的 PDF 库。您的标签提供了 的选择。我在这里为 Java 选择了 iText 5.5.x;使用 PDFBox 也应该可以实现模拟解决方案。我不确定 Pdftotext。

检查您的 PDF 的内部结构会发现:

  • 显示说明的文本按阅读顺序排列。

    因此,您不需要对它们进行排序以进行文本提取,您可以将解决方案基于SimpleTextExtractionStrategy

  • 这里或那里显示了许多没有意义的单个空白字符,干扰了实际文本。

    您应该过滤这些多余的空格字符。

  • 数据集分隔线是唯一填充的路径。此外,这些分隔线也是按“阅读顺序”绘制的。

    因此,您已经可以通过填充操作识别它们,无需分析路径形式,并且当您识别它们时,您可以在文本提取策略输出中添加标记。

因此,您可以通过扩展 SimpleTextExtractionStrategy 来实现您的任务:

public class SimpleDividerAwareTextExtractionStrategy extends SimpleTextExtractionStrategy implements TextExtractionStrategy, ExtRenderListener {
    @Override
    public void renderText(TextRenderInfo renderInfo) {
        if (!" ".equals(renderInfo.getText()))
            super.renderText(renderInfo);
    }

    @Override
    public void modifyPath(PathConstructionRenderInfo renderInfo) { }

    @Override
    public Path renderPath(PathPaintingRenderInfo renderInfo) {
        if (renderInfo.getOperation() == PathPaintingRenderInfo.FILL)
            appendTextChunk("\n----------\n");
        return null;
    }

    @Override
    public void clipPath(int rule) { }
}

(SimpleDividerAwareTextExtractionStrategy 助手类)

将此策略应用于您的示例 PDF:

PdfReader reader = new PdfReader(SOURCE);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
SimpleDividerAwareTextExtractionStrategy strategy = new SimpleDividerAwareTextExtractionStrategy();
for (int i = 1; i <= reader.getNumberOfPages(); i++)
    parser.processContent(i, strategy);
String content = strategy.getResultantText();

System.out.println(content);

(DividerAwareTextExtraction 测试testSimple419494453ThisIsASampleDocument)

一个得到:

This is a sample document
----------

SAM PARTNERS LLC.
Existing Client with Premium
Support, Retail Client
123 Popsicle Ave
Candyville IA 50325
512-512-5555
Order Number Order Quantity
RTL123 45
RTL456 25
RTL324 95
RTL457 100
----------

DUNDER MIFFLIN
Existing Client with Standard
Support, Corporate Client
123 Lolipop Ave
Candyville PA 21325
215-512-5555
Order Number Order Quantity
RTL1234 400
RTL4565 200
----------

Mobile PARTNERS LLC.
New Client with Premium
Support, Retail Client
123 First Ave
Nashville TN 51325
514-512-5555
Order Number Order Quantity
RTL123 45
RTL456 25
RTL324 95
RTL457 25
RTL457 25
RTL457 25
RTL457 25
----------

BLUEBERRY MUFFIN
New Client, Corporate Client
123 STORM Ave
Hershey PA 50325
216-512-5555
Order Number Order Quantity
RTL1234 400
RTL4565 200
----------

要提取数据集,您只需要找到分隔符字符串----------(当然您可以在SimpleDividerAwareTextExtractionStrategy 中使用不同的字符串),然后读取直到Order Number Order Quantity 的所有行以获取名称和地址数据,然后然后读取所有行直到下一个分隔符字符串以获取订单信息。

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2011-05-01
    • 2013-09-23
    • 2020-07-08
    相关资源
    最近更新 更多