2012-08-10 11 views
8

Ich muss ein PDF-Dokument analysieren. Ich habe bereits den Parser implementiert und die Bibliothek iText verwendet und bis jetzt funktionierte es ohne Probleme.Seltsame Leerzeichen beim Analysieren eines PDFs

Aber nein, ich muss ein anderes Dokument analysieren, das sehr seltsame Leerzeichen in der Mitte der Wörter bekommt. Als Beispiel erhalte ich:

Vo rber eitung auf sterben Motorr adsaison. Viele Motorr adf ahr er

Alle fett Worte verbunden sein sollte, aber irgendwie die PDF-Parser ist das Hinzufügen von Leerzeichen in den Worten. Aber wenn ich den Inhalt aus der PDF in eine Textdatei kopiere und einfüge, bekomme ich diese Leerzeichen nicht.

Zuerst dachte ich, es ist wegen der PDF-Parsing-Bibliothek, die ich benutze, aber auch mit einer anderen Bibliothek bekomme ich genau das gleiche Problem.

Ich habe die singleSpaceWidth aus den geparsten Wörtern untersucht und festgestellt, dass es immer dann variiert, wenn ein Whitespace hinzugefügt wird. Ich habe versucht, sie manuell zusammenzustellen. Aber da es nicht wirklich ein Muster gibt, um die Wörter neu zu kombinieren, ist es fast unmöglich.

Hat jemand anderes ein ähnliches Problem oder sogar eine Lösung für dieses Problem?

Wie gewünscht, hier einige weitere Informationen:

Parsing mit 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); 
} 

Hier die SemTextExtractionStrategy-Methode, die den t ext. Es füge ich manuell nach jedem geparsten Wort ein Leerzeichen, aber irgendwie hat es die Wörter in der Erkennung aufgeteilt:

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

    this.pageNumber = pageNumber; 

    String text = renderInfo.getText(); 

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

    .... 
} 

sich hier die ganze SemTextExtraction Klasse ist aber dort nur die Methode ruft von oben (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); 
     } 
    } 
} 
+0

Bitte sagen Sie der Version von iText, die Sie verwenden, und irgendwie müssen Sie auch die PDF-Datei und den Code, mit dem Sie analysieren, bereitstellen. – Eugene

+0

Alle Informationen im obigen Beitrag hinzugefügt. – Prine

+0

Was ist mit der von Ihnen verwendeten TextExtractionStrategy-Klasse? – Eugene

Antwort

2

Ich habe die angegebene PDF-Datei mit folgendem Ghostscript Befehl verarbeitet:

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

Dieser Befehl eine Datei out.pdf erstellt, die nicht die Stream-Kodierungen haben, so ist es besser lesbar. Der interessante Teil ist in der Leitung 52, die ich zur besseren Lesbarkeit in mehrere Zeilen aufgeteilt:

[ 
    (&;&)-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 

Zwischen den Klammern sind die Textzeichen. Ich habe einige von ihnen geändert und habe in der gerenderten PDF-Datei gesehen, welches Zeichen welche Glyphe darstellt. Dann habe ich den Text entschlüsselt:

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

Also gibt es tatsächlich Leerzeichen zwischen den Zeichen. In Ihrem Fall ist dies wahrscheinlich das Kerning der Schriftart. Die Frage ist nun, wie Ihre PDF-Bibliothek diesen Leerraum interpretiert, und es scheint mir, dass sogar "negativer Leerraum" in dem resultierenden String in ein Leerzeichen gerendert wird.

+0

Gibt es eine Möglichkeit, diese oder eine Implementierung loszuwerden? – NinjaOnSafari

+0

und mit welchem ​​Tool haben Sie das PDF erstellt? – NinjaOnSafari

+0

Es ist Ghostscript; Ich habe die Antwort bearbeitet, um das klarzustellen. Danke für den Tipp. –

0

Da das Dokument, das Sie in Spalten aufgeteilt haben, ist der offensichtliche Fehler in der

SemTextExtractionStrategy

Klasse. Ich nehme an, dass die Klasse ColumnDetecter die ist, die wahrscheinlich und nicht iText verantwortlich gemacht wird. Ich kann nur annehmen, dass es basierend auf der Größe der Spalte implementiert wird, und ruft dann den darauf basierenden Text ab.

Wenn Sie nur den Text möchten, dann könnte die Implementierung einfacher sein, basierend auf der Größe der Spalte.

+0

Danke für Ihre Antwort. Ich werde auf jeden Fall einen Blick in den ColumnDetector werfen. Aber die parseText-Methode stammt aus dieser Klasse und dort bekomme ich die Ausgabe direkt aus der iText-Bibliothek, wo die Wörter bereits aufgeteilt sind. – Prine

1

Die Whitespaces in pdf sind ein bekanntes Problem, wie hier von Roland von der Antwort beschrieben und auch auf den ersten Kommentar von https://issues.apache.org/jira/browse/TIKA-724

Die Antwort, die auch für mich gearbeitet wird derjenige von huuhungus bei https://github.com/smalot/pdfparser/issues/72 gesehen

, die PDFParser spezifisch ist, und es ist, den Code zu ändern, die dem PDFParser fügt tatsächlich diesen zusätzlichen Platz, wenn Sie wissen, dass Sie dieses Problem haben:

sr c/Smalot/PdfParser/Object.php diese Zeile auf Kommentar

$text .= ' '; 

nicht es vollständig zu beheben, aber es ist zu akzeptablen

Anderen Bibliotheken auch ähnliche temporäre Korrekturen haben kann, so dass sie sich mit diesem Thema helfen könnten in manchen Fällen.

+0

iText 5.2.1 ist jetzt eine alte Version. Aktuelle Versionen haben Eigenschaften/überschreibbare Methoden zur Feineinstellung, in welchen Situationen iText ein Leerzeichen hinzufügt und in welchen nicht. Nie einen Platz hinzufügen, ist auch eine schlechte Wahl im Allgemeinen, zahlreiche PDFs dann wird ihr Text mit kaum irgendwelchen Räumen extrahiert. – mkl

Verwandte Themen