10

我需要解析一个 PDF 文档。我已经实现了解析器并使用了iText库,到目前为止它可以正常工作。

但是不,我需要解析另一个在单词中间出现非常奇怪的空格的文档。例如,我得到:

Vo rber eitung auf die Motorr adsaison。Viele Motorr adf ahr er

所有粗体字都应该连接起来,但 PDF 解析器会以某种方式在字词中添加空格。但是当我将 PDF 中的内容复制并粘贴到文本文件中时,我没有得到这些空格。

首先,我认为这是因为我正在使用 PDF Parsing 库,但对于另一个库,我也遇到了完全相同的问题。

我查看singleSpaceWidth了解析后的单词,我注意到它总是在变化,当它添加一个空格时。我试图手动将它们放在一起。但由于没有真正的模式来重新组合单词,这几乎是不可能的。

有没有其他人有类似的问题,甚至有解决该问题的方法?

根据要求,这里有更多信息:

使用 SemTextExtractionStrategy 解析:

PdfReader reader = new PdfReader("data/SpecialTests/SuedostSchweiz/" + src);

SemTextExtractionStrategy semTextExtractionStrategy = new SemTextExtractionStrategy();

for (int i = 1; i <= reader.getNumberOfPages(); i++) {
    // Set the page number on the strategy. Is used in the Parsing strategies.
    semTextExtractionStrategy.pageNumber = i;

    // Parse text from page
    PdfTextExtractor.getTextFromPage(reader, i, semTextExtractionStrategy);
}

这里是实际解析文本的 SemTextExtractionStrategy 方法。在那里,我在每个解析的单词之后手动添加了一个空格,但它确实在检测中拆分了单词:

@Override
public void parseText(TextRenderInfo renderInfo, int pageNumber) {      

    this.pageNumber = pageNumber;

    String text = renderInfo.getText();

    currTextBlock.getText().append(text + " ");

    ....
}

这是整个 SemTextExtraction 类,但在那里它只调用上面的方法(parseText):

public class SemTextExtractionStrategy implements TextExtractionStrategy {

    // Text Extraction Strategies
    public ColumnDetecter columnDetecter = new ColumnDetecter();

    // Image Extraction Strategies
    public ImageRetriever imageRetriever = new ImageRetriever();

    public int pageNumber = -1;

    public ArrayList<TextParsingStrategy> textParsingStrategies = new ArrayList<TextParsingStrategy>();
    public ArrayList<ImageParsingStrategy> imageParsingStrategies = new ArrayList<ImageParsingStrategy>();

    public SemTextExtractionStrategy() {

        // Add all text parsing strategies which are later on applied on the extracted text
        // textParsingStrategies.add(fontSizeMatcher);
        textParsingStrategies.add(columnDetecter);

        // Add all image parsing strategies which are later on applied on the extracted text
        imageParsingStrategies.add(imageRetriever);
    }

    @Override
    public void beginTextBlock() {

    }

    @Override
    public void renderText(TextRenderInfo renderInfo) {
        // TEXT PARSING
        for(TextParsingStrategy strategy : textParsingStrategies) {
            strategy.parseText(renderInfo, pageNumber);
        }
    }

    @Override
    public void endTextBlock() {

    }

    @Override
    public void renderImage(ImageRenderInfo renderInfo) {
        for(ImageParsingStrategy strategy : imageParsingStrategies) {
            strategy.parseImage(renderInfo);
        }
    }
}
4

3 回答 3

5

pdf 中的空格是一个已知问题,如 Roland 在此处的答案所述,并且在 https://issues.apache.org/jira/browse/TIKA-724的第一条评论中也可以看到

对我也有用的答案是 huuhungus 在 https://github.com/smalot/pdfparser/issues/72看到的答案

这是特定于 PDFParser 的,如果你知道你会遇到这个问题,它是更改实际上将这个额外空间添加到 PDFParser 的代码:

src/Smalot/PdfParser/Object.php 注释掉这一行

   $text .= ' ';

没有完全解决,但可以接受

其他库也可能有类似的临时修复,因此在某些情况下它们可以帮助解决这个问题。

于 2017-01-05T12:52:28.423 回答
4

我已经使用以下Ghostscript命令处理了给定的 PDF 文件:

gs -o out.pdf -q -sDEVICE=pdfwrite -dOptimize=false -dUseFlageCompression=false -dCompressPages=false -dCompressFonts=false whitespacesProblem.pdf

该命令创建了一个文件out.pdf,该文件没有流编码,因此可读性更好。有趣的部分在第 52 行,为了便于阅读,我将其拆分为多行:

[
  (&;&)-287.988
  (672744)29.9906
  (+\(%)30.01
  (+!4)29.9876
  (&4)-287.989
  (%4)30.0039
  (&1&8)-287.975
  (3=\)!)-288.021
  (*&4)30.0212
  (&=23)-287.996
  (+1%)-287.99
  (\(=&)-288.011
  (8&1&)-287.974
  (672744)29.9906
  (+\(3+=378$)-250.977
  (#7\)!)
]TJ

括号之间是文本字符。我更改了其中的一些并查看了渲染的 PDF 文件,以查看哪个字符代表哪个字形。然后我解码了文本:

[
  (ele)-287.988
  (Motorr)29.9906 ***
  (adf)30.01 ***
  (ahr)29.9876 ***
  (er)-287.989
  (fr)30.0039
  (euen)-287.975
  (sich)-288.021
  ...
]

所以字符之间确实有空格。在您的情况下,这可能是字体的字距调整。现在的问题是您的 PDF 库如何解释这个空格,在我看来,即使是“负空格”也被渲染到结果字符串中的空格中。

于 2012-09-08T10:45:12.310 回答
0

因为您拥有的文档被分成几列,所以明显的错误在

半文本提取策略

班级。我假设ColumnDetecter类可能是应该受到指责的,而不是 iText。我只能假设它是根据列的大小来实现的,然后根据它来检索文本。

如果您只想要文本,那么根据列的大小,实现可能会更简单。

于 2012-08-10T13:34:49.830 回答