Discussion:
Text aus einer PDF Datei extrahieren
(zu alt für eine Antwort)
Jens-Erich Lange
2008-04-08 15:48:41 UTC
Permalink
Moin,

sollte ja gar nicht so schwer sein, dachte ich mir. Einfach
alle Binärdaten zwischen den Worten "stream" und "endstream"
mit zlib entpacken und den Plain-Text nach "BT" und "ET"
parsen...

So jedenfalls lautet die Anleitung hier:
http://www.codeproject.com/KB/cpp/ExtractPDFText.aspx

Ich habe folgendes Delphi-Interface für zlib verwendet:
http://www.dellapasqua.com/delphizlib/

mein Versuch sieht bislang so aus:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

uses
ZlibEx;


function TForm1.DecodeText(Data: string): string;
begin
// Hier kommt die eigentliche Auswertung des
// dekomprimierten PDF Objektes
Result := '';
end;


function TForm1.PDFread(FileName: string): string;
var
f: file;
i: longint;
Source: string;
Stream: string;
begin
Result := '';
AssignFile(f, FileName);
Reset(f, 1);
i := FileSize(f);
SetLength(Source, i);
Blockread(f, Source[1], i);
CloseFile(f);

repeat
i := pos('stream', Source);
if (i > 0) then
begin
delete(Source, 1, i + 5);
i := pos('endstream', Source);
if (i > 0) then
begin
Stream := copy(Source, 1, i - 1);
delete(Source, 1, i + 8);

if (length(Stream) > 1) and (Stream[1] = #13) and (Stream[2] = #10) then delete(Stream, 1,
2)
else if (length(Stream) > 0) and (Stream[1] = #10) then delete(Stream, 1, 1);

if (length(Stream) > 1) and (Stream[length(Stream) - 1] = #13) and (Stream[length(Stream)] =
#10) then delete(Stream, length(Stream) - 1, 2)
else if (length(Stream) > 0) and (Stream[length(Stream)] = #10) then delete(Stream,
length(Stream), 1);

ZFastDecompressString(Stream);

if (Result <> '') then Result := Result + #13 + #10;
Result := Result + DecodeText(Stream);
end;
end;
until (i = 0);
end;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Das Entpacken des PDF streams scheitert immer mit einem EConversion
Error.

Das Packen und Entpacken mit zlib hat in anderen Anwendungen immer
gut funktioniert, nur mit dem PDF-Stream klappt es irgendwie nicht...

Danke für Eure Tipps,
Jens


P.S. Ach ja ich möchte die Funktion wirklich gern in mein Programm
integrieren. Dienstprogramme dafür(auch kostenlose) gibt es ja wie
Sand am Meer).

Notfalls werde ich auf die DLL-Lösung von Ingo Schmoekel zurückkommen.
--
Dynamo Software, Jens-Erich Lange e.K.
Seestraße 17, D-23829 Wittenborn, Germany
Tel (04554) 7052-10, Fax (04554) 7052-11, Mobil (0170) 407 29 96
HR A613, Amtsgericht Bad Segeberg, USt ID: DE 134331669
Wolfgang Fellger
2008-04-08 15:58:17 UTC
Permalink
Post by Jens-Erich Lange
Stream := copy(Source, 1, i - 1);
delete(Source, 1, i + 8);
^^^^^^

Soll das nicht eher "Stream" sein?
Du könntest auch gleich die acht Bytes weniger kopieren, dann musst du sie
nicht löschen :-)
--
Wolfgang Fellger
Jens-Erich Lange
2008-04-08 17:55:07 UTC
Permalink
Post by Wolfgang Fellger
Post by Jens-Erich Lange
Stream := copy(Source, 1, i - 1);
delete(Source, 1, i + 8);
^^^^^^
Soll das nicht eher "Stream" sein?
Nein, "Source" stimmt schon. "Stream" ist ein Teilstring
aus "Source" (eben der PDF Object-Stream) und die delete-
Orgien kürzen den Quellstring so dass ich in der Schleife
wiederholt nach den Markern "stream" und "endstream" per
Pos() suchen kann.
Post by Wolfgang Fellger
Du könntest auch gleich die acht Bytes weniger kopieren,
dann musst du sie nicht löschen :-)
delete(Source, 1, i+8) kürzt den Quellstring so, dass das
"endstream" verschwindet und ich somit im nächten Schleifen-
durchlauf den nächsten Block suchen kann.

Dies ist zwar alles andere als elegant, aber an dieser
Baustelle kann ich später noch rumhübschen.

Die Blockentnahme funktioniert auch insofern, dass bei
meinem 3-seitigen PDF Dokument die drei dazugehörigen
Object-Streams in der Stringvariable "Stream" landen.

Nur das entpacken funktioniert nicht...

Jens
Ulrich Kobsa
2008-04-12 19:25:23 UTC
Permalink
Hallo,

mit diesem Ansatz wirst Du wahrscheinlich nicht viel Gluck haben. Das
Problem bei Textextraktion aus PDF Dateien ist die Art und Weise, wie
Text in PDFs gespeichert wird:
In ganz einfachen Fallen steht der Text plain drinnen. Dann gibt es
noch die Variante, wo der Text als einfacher Stream drinnen steht (was
Du gerade machen willst), Dann noch die Variante, wo Text als
zeichenweiser Unicode-Wert drinnen steht. Oder auch die Variante, wo
das Textobject selbst wieder Teil eines gro?eren Streams ist.
Schau mal in die Spec von Adobe rein damit Du einen Uberblick kriegst,
was es so alles an Moglichkeiten gibt.

Wenn Du genau vorhersagen kannst, in welcher Art Text in den von Dir zu
verarbeitenden PDFs vorkommt, dann kannst Du eine Eigenentwicklung
versuchen. Ansonsten kauf Dir externe Komponenten und teste vorher, ob
sie die Textextraktion auch wirklich gut konnen!
QuickPDf ist zum Beispiel nicht wirklich schlecht, kann aber auch nicht
alle Arten von Texte extrahieren.
Das SDK von PDFXChange ist sehr gut. Ich verwende das beruflich und
bisher hab ich noch keine Probleme mit Dokumenten gehabt (Allerdings
geht die Software mit dieser Textextraktion gerade erst in die
Beta-Phase so da? noch nicht wirklich viele Kunden damit gearbeitet
haben).

Gru?e,
Uli
Hans-Peter Diettrich
2008-04-12 23:10:53 UTC
Permalink
Post by Ulrich Kobsa
Du gerade machen willst), Dann noch die Variante, wo Text als
zeichenweiser Unicode-Wert drinnen steht.
Die übelste Variante, die ich erlebt habe, war ein zweispaltiges
Dokument im Blocksatz. Gespeichert als Buchstabensuppe, mit Makros für
Positionsangaben für Kerning, Leeraum, Spalten- und Zeilenwechsel. Ich
habe mir ein paar Makros angeschaut, und es dann aufgegeben, den Text
ohne Nachbau eines kompletten Automaten aus den Zeichen rekonstruieren
zu wollen.

DoDi
Jens-Erich Lange
2008-04-14 07:01:55 UTC
Permalink
Post by Ulrich Kobsa
Du gerade machen willst), Dann noch die Variante, wo Text als
zeichenweiser Unicode-Wert drinnen steht.
Die übelste Variante, die ich erlebt habe, war ein zweispaltiges Dokument im Blocksatz. Gespeichert
als Buchstabensuppe, mit Makros für Positionsangaben für Kerning, Leeraum, Spalten- und
Zeilenwechsel. Ich habe mir ein paar Makros angeschaut, und es dann aufgegeben, den Text ohne
Nachbau eines kompletten Automaten aus den Zeichen rekonstruieren zu wollen.
Danke für die Hinweise. Ich möchte fest definierte Dokumente
verarbeiten, nämlich Kontoauszüge.

Ich mache meine Bankgeschäfte ohne Banking-Software sondern mit
dem Internet Browser. Auszüge bekomme ich als PDF Datei. Jetzt
möchte ich eine kleine Mini-Kontenverwaltungssoftware schreiben,
die mir im Grunde genommen nur die Buchungszeilen der Konten
speichert.

Den PDF-Import möchte ich als Plug-In gestalten, so dass sich
bei einem Formatwechsel (oder gar Bankwechsel) hier nur das
Plug-In anpassen muss.

Jens

Lesen Sie weiter auf narkive:
Loading...