解析PDF时出现奇怪的空格

Pri*_*ine 9 java pdf whitespace itext pdf-parsing

我需要解析PDF文档.我已经实现了解析器并使用了库iText,直到现在它都没有任何问题.

但是,我不需要解析另一个在单词中间会得到非常奇怪的空格的文档.作为例子,我得到:

Vo rber eitung auf die Motorr adsaison.Viele Motorr ADF AHR呃

所有大胆的单词都应该连接起来,但不知何故,PDF Parser会在单词中添加空格.但是当我将PDF中的内容复制并粘贴到文本文件中时,我得不到这些空格.

首先我认为这是因为我正在使用的PDF解析库,而且还有另一个库我得到了完全相同的问题.

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);
}
Run Code Online (Sandbox Code Playgroud)

这里实际解析文本的SemTextExtractionStrategy方法.我在每个解析的单词之后手动添加一个空格,但不知何故它会在检测中拆分单词:

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

    this.pageNumber = pageNumber;

    String text = renderInfo.getText();

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

    ....
}
Run Code Online (Sandbox Code Playgroud)

这是整个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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Rol*_*lig 5

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

gs -o out.pdf -q -sDEVICE=pdfwrite -dOptimize=false -dUseFlageCompression=false -dCompressPages=false -dCompressFonts=false whitespacesProblem.pdf
Run Code Online (Sandbox Code Playgroud)

该命令创建了一个文件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
Run Code Online (Sandbox Code Playgroud)

括号之间是文本字符。我更改了其中一些并观看渲染的 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
  ...
]
Run Code Online (Sandbox Code Playgroud)

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


小智 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 .= ' ';
Run Code Online (Sandbox Code Playgroud)

没有完全修复它,但它是可以接受的

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