Python-Modul zum Konvertieren von PDF in Text [geschlossen]

385

Gibt es ein Python-Modul zum Konvertieren von PDF-Dateien in Text? Ich habe einen in Activestate gefundenen Code ausprobiert, der pypdf verwendet, aber der generierte Text hatte kein Leerzeichen dazwischen und war nutzlos.

cnu
quelle
1
Ich suchte nach einer ähnlichen Lösung. Ich muss nur den Text aus der PDF-Datei lesen. Ich brauche die Bilder nicht. pdfminer ist eine gute Wahl, aber ich habe kein einfaches Beispiel zum Extrahieren des Textes gefunden. Endlich habe ich diese SO-Antwort erhalten ( stackoverflow.com/questions/5725278/… ) und benutze sie jetzt.
Nayan
2
Da die Frage geschlossen wurde, habe ich sie auf dem Stack Exchange erneut veröffentlicht, der Softwareempfehlungen gewidmet ist, falls jemand eine neue Antwort schreiben möchte: Python-Modul zum Konvertieren von PDF in Text
Franck Dernoncourt
1
Die einzige Lösung, die für mich für UTF-8-Inhalte funktioniert hat: Apache Tika
Shoham
Ich möchte die Liste der verfügbaren Optionen für die Konvertierung von PDF in Text in Python aktualisieren. GroupDocs.Conversion Cloud SDK für Python konvertiert PDF in Text genau.
Tilal Ahmad

Antworten:

142

Probieren Sie PDFMiner aus . Es kann Text aus PDF-Dateien im HTML-, SGML- oder "Tagged PDF" -Format extrahieren.

Das Tagged PDF-Format scheint das sauberste zu sein, und wenn Sie die XML-Tags entfernen, bleibt nur der bloße Text übrig.

Eine Python 3-Version ist verfügbar unter:

David Crow
quelle
2
Ich habe gerade eine Antwort hinzugefügt, in der beschrieben wird, wie pdfminer als Bibliothek verwendet wird.
Codeape
24
Keine Python 3-Unterstützung :(
Karl Adler
1
Die Antwort, die ich in diesem Thread gegeben habe , kann für Leute nützlich sein, die sich diese Antwort ansehen und sich fragen, wie sie die Bibliothek verwenden sollen. Ich gebe ein Beispiel für die Verwendung der PDFMiner-Bibliothek zum Extrahieren von Text aus dem PDF. Da die Dokumentation etwas spärlich ist, dachte ich, dass es ein paar Leuten helfen könnte.
DuckPuncher
17
In Bezug auf Python 3 gibt es eine sechsbasierte
Denis Cornehl
1
Beispielcode unter stackoverflow.com/a/26495057/125617
Renaud
136

Das PDFMiner- Paket hat sich seit der Veröffentlichung von codeape geändert .

BEARBEITEN (erneut):

PDFMiner wurde in der Version erneut aktualisiert 20100213

Sie können die installierte Version folgendermaßen überprüfen:

>>> import pdfminer
>>> pdfminer.__version__
'20100213'

Hier ist die aktualisierte Version (mit Kommentaren zu dem, was ich geändert / hinzugefügt habe):

def pdf_to_csv(filename):
    from cStringIO import StringIO  #<-- added so you can copy/paste this to try it
    from pdfminer.converter import LTTextItem, TextConverter
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTTextItem):
                    (_,_,x,y) = child.bbox                   #<-- changed
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)  #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8")  #<-- changed 
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       #<-- changed
    parser.set_document(doc)     #<-- added
    doc.set_parser(parser)       #<-- added
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

Bearbeiten (noch einmal):

Hier ist ein Update für die neueste Version in pypi , 20100619p1. Kurz ersetzt ich LTTextItemmit LTCharund übergeben eine Instanz von LAParams zum CsvConverter Konstruktor.

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter    #<-- changed
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, LTChar):               #<-- changed
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child.text.encode(self.codec)

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())  #<-- changed
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

BEARBEITEN (noch einmal):

Für die Version aktualisiert 20110515(danke an Oeufcoque Penteano!):

def pdf_to_csv(filename):
    from cStringIO import StringIO  
    from pdfminer.converter import LTChar, TextConverter
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item._objs:                #<-- changed
                if isinstance(child, LTChar):
                    (_,_,x,y) = child.bbox                   
                    line = lines[int(-y)]
                    line[x] = child._text.encode(self.codec) #<-- changed

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, codec="utf-8", laparams=LAParams())
        # becuase my test documents are utf-8 (note: utf-8 is the default codec)

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(fp)       
    parser.set_document(doc)     
    doc.set_parser(parser)       
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        if page is not None:
            interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()
tgray
quelle
1
In [6]: pdfminer importieren In [7]: pdfminer .__ version__ Out [7]: '20100424' In [8]: aus pdfminer.converter LTTextItem importieren LTContainer LTLine LTRect LTTextGroup LITERAL_DEVICE_RGB LTFigur LTPage LTText LTTextLine
Skylar Saveland
@skyl, der obige Code gilt für die vorherige Version '20100213'. Aus der Liste der Änderungen auf ihrer Website, es sieht aus wie sie sich verändert LTTextItemzu LTChar. unixuser.org/~euske/python/pdfminer/index.html#changes
tgray
2
@Oeufcoque Penteano, danke! Ich habe der Antwort für die Version 20110515gemäß Ihrem Kommentar einen weiteren Abschnitt hinzugefügt .
Tgray
1
Die Antwort von @ user3272884 funktioniert vom 5-1-2014
jmunsch
1
Ich musste das gleiche Problem heute lösen, den Code von tgray ein wenig modifizieren, um Informationen über Leerzeichen zu extrahieren, und ihn hier
posten
67

Da keine dieser Lösungen die neueste Version von PDFMiner unterstützt, habe ich eine einfache Lösung geschrieben, die mit PDFMiner den Text eines PDFs zurückgibt. Dies funktioniert für diejenigen, bei denen Importfehler auftretenprocess_pdf

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
from cStringIO import StringIO

def pdfparser(data):

    fp = file(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print data

if __name__ == '__main__':
    pdfparser(sys.argv[1])  

Siehe folgenden Code, der für Python 3 funktioniert:

import sys
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter
from pdfminer.layout import LAParams
import io

def pdfparser(data):

    fp = open(data, 'rb')
    rsrcmgr = PDFResourceManager()
    retstr = io.StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    # Create a PDF interpreter object.
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    # Process each page contained in the document.

    for page in PDFPage.get_pages(fp):
        interpreter.process_page(page)
        data =  retstr.getvalue()

    print(data)

if __name__ == '__main__':
    pdfparser(sys.argv[1])  
user3272884
quelle
2
Dies ist das erste Snippet, das ich gefunden habe und das tatsächlich mit seltsamen PDF-Dateien funktioniert (insbesondere mit den kostenlosen E-Books, die man von packtpub bekommen kann). Jeder zweite Code gibt nur das seltsam codierte Rohmaterial zurück, aber Ihr Code gibt tatsächlich Text zurück. Vielen Dank!
Somada141
Sie möchten wahrscheinlich retstr.seek (0) ausführen, nachdem Sie Daten abgerufen haben, oder Sie sammeln Text von allen Seiten.
Tshirtman
2
Um mit zu verwenden python3, muss man neben den offensichtlichen Klammern nach dem printBefehl den fileBefehl durch das Paket ersetzen openund StringIOaus dem Paket importierenio
McLawrence
1
Beeindruckend. Dieser Block hat beim ersten Kopieren perfekt funktioniert. Erstaunlich! Weiter zum Parsen und Korrigieren der Daten und ohne Stress bei der Eingabe.
SecsAndCyber
1
pdfminer funktioniert nicht für python3. Dieser Code funktioniert nicht für pdfminer3k
thang
47

Pdftotext Ein Open-Source-Programm (Teil von Xpdf), das Sie von Python aus aufrufen können (nicht das, wonach Sie gefragt haben, aber möglicherweise nützlich sind). Ich habe es ohne Probleme benutzt. Ich denke, Google verwendet es in Google Desktop.

Jamie
quelle
6
Dies scheint das nützlichste der hier aufgeführten Tools zu sein, mit der -layoutOption, Text an derselben Position wie im PDF zu halten. Wenn ich nur herausfinden könnte, wie ich den Inhalt einer PDF-Datei darin ableiten kann.
Matthew Schinckel
Nach dem Testen mehrerer Lösungen scheint diese die einfachste und robusteste Option zu sein. Kann von Python einfach mit einem Tempfile umbrochen werden, um zu bestimmen, wohin die Ausgabe geschrieben wird.
Cerin
Cerin , verwenden Sie '-' als Dateinamen, um die Ausgabe an stdout umzuleiten. Auf diese Weise können Sie einfache subprocess.check_output verwenden, und dieser Aufruf würde sich wie eine interne Funktion anfühlen.
Strg-C
Nur um jeden zu verstärken, der es benutzt. . . pdftotextscheint sehr gut zu funktionieren, aber es braucht ein zweites Argument, das ein Bindestrich ist, wenn Sie die Ergebnisse auf stdout sehen wollen.
Gordon Linoff
1
Dadurch werden alle PDF-Dateien ab dem aktuellen Ordner rekursiv konvertiert: find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;Standardmäßig nehmen die generierten Dateien den ursprünglichen Namen mit der .txtErweiterung an.
ccpizza
43

pyPDF funktioniert einwandfrei (vorausgesetzt, Sie arbeiten mit wohlgeformten PDFs). Wenn Sie nur den Text (mit Leerzeichen) möchten, können Sie einfach Folgendes tun:

import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
    print page.extractText()

Sie können auch problemlos auf Metadaten, Bilddaten usw. zugreifen.

Ein Kommentar im Code "extractText" enthält folgende Hinweise:

Suchen Sie alle Textzeichnungsbefehle in der Reihenfolge, in der sie im Inhaltsdatenstrom angegeben sind, und extrahieren Sie den Text. Dies funktioniert für einige PDF-Dateien gut, für andere jedoch schlecht, je nach verwendetem Generator. Dies wird in Zukunft verfeinert. Verlassen Sie sich nicht auf die Reihenfolge des Texts, der aus dieser Funktion kommt, da sich dieser ändert, wenn diese Funktion komplexer wird.

Ob dies ein Problem ist oder nicht, hängt davon ab, was Sie mit dem Text tun (z. B. wenn die Reihenfolge keine Rolle spielt, ist es in Ordnung, oder wenn der Generator dem Stream Text in der Reihenfolge hinzufügt, in der er angezeigt wird, ist es in Ordnung). . Ich habe pyPdf-Extraktionscode im täglichen Gebrauch, ohne Probleme.

Tony Meyer
quelle
7
Keine Unicode-Unterstützung :(
PanosJee
7
pyPdf unterstützt jetzt UTF.
lbolla
2
Diese Bibliothek sieht aus wie Müll. Das Testen auf einem zufälligen PDF gibt mir den Fehler "pyPdf.utils.PdfReadError: EOF-Marker nicht gefunden"
Cerin
4
Aus der Frage: Der generierte Text hatte keinen Abstand dazwischen und war nutzlos . Ich habe pyPDF verwendet und das gleiche Ergebnis erzielt - Text wird ohne Leerzeichen zwischen Wörtern extrahiert.
Jordan Reiter
Wenn ich die Funktion page.extractText () ausführe, wird der Fehler 'TypeError: Objekt' Bytes 'kann nicht implizit in str konvertiert werden' angezeigt. Wie kann ich damit umgehen?
Juankysmith
21

Sie können pdfminer auch ganz einfach als Bibliothek verwenden. Sie haben Zugriff auf das Inhaltsmodell des PDFs und können Ihre eigene Textextraktion erstellen. Ich habe dies getan, um PDF-Inhalte mit dem folgenden Code in durch Semikolon getrennten Text zu konvertieren.

Die Funktion sortiert die TextItem-Inhaltsobjekte einfach nach ihren y- und x-Koordinaten und gibt Elemente mit derselben y-Koordinate wie eine Textzeile aus, wobei die Objekte in derselben Zeile mit ';' getrennt werden. Figuren.

Mit diesem Ansatz konnte ich Text aus einem PDF extrahieren, aus dem kein anderes Tool Inhalte extrahieren konnte, die zum weiteren Parsen geeignet waren. Andere Tools, die ich ausprobiert habe, sind pdftotext, ps2ascii und das Online-Tool pdftextonline.com.

pdfminer ist ein unschätzbares Werkzeug für das PDF-Scraping.


def pdf_to_csv(filename):
    from pdflib.page import TextItem, TextConverter
    from pdflib.pdfparser import PDFDocument, PDFParser
    from pdflib.pdfinterp import PDFResourceManager, PDFPageInterpreter

    class CsvConverter(TextConverter):
        def __init__(self, *args, **kwargs):
            TextConverter.__init__(self, *args, **kwargs)

        def end_page(self, i):
            from collections import defaultdict
            lines = defaultdict(lambda : {})
            for child in self.cur_item.objs:
                if isinstance(child, TextItem):
                    (_,_,x,y) = child.bbox
                    line = lines[int(-y)]
                    line[x] = child.text

            for y in sorted(lines.keys()):
                line = lines[y]
                self.outfp.write(";".join(line[x] for x in sorted(line.keys())))
                self.outfp.write("\n")

    # ... the following part of the code is a remix of the 
    # convert() function in the pdfminer/tools/pdf2text module
    rsrc = PDFResourceManager()
    outfp = StringIO()
    device = CsvConverter(rsrc, outfp, "ascii")

    doc = PDFDocument()
    fp = open(filename, 'rb')
    parser = PDFParser(doc, fp)
    doc.initialize('')

    interpreter = PDFPageInterpreter(rsrc, device)

    for i, page in enumerate(doc.get_pages()):
        outfp.write("START PAGE %d\n" % i)
        interpreter.process_page(page)
        outfp.write("END PAGE %d\n" % i)

    device.close()
    fp.close()

    return outfp.getvalue()

UPDATE :

Der obige Code wurde gegen eine alte Version der API geschrieben, siehe meinen Kommentar unten.

Codeape
quelle
Welche Art von Plugins brauchst du, damit das funktioniert? Ich habe pdfminer heruntergeladen und installiert, aber es ist nicht genug ...
kxk
1
Der obige Code wurde gegen eine alte Version von PDFminer geschrieben. Die API wurde in neueren Versionen geändert (zum Beispiel ist das Paket jetzt pdfminernicht mehr pdflib). Ich schlage vor, Sie werfen einen Blick auf die Quelle pdf2txt.pyin der PDFminer-Quelle. Der obige Code wurde von der alten Version dieser Datei inspiriert.
Codeape
17

slate ist ein Projekt, das die Verwendung von PDFMiner aus einer Bibliothek sehr einfach macht:

>>> with open('example.pdf') as f:
...    doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'   
Tim McNamara
quelle
1
Beim Ausführen von "import slate" wird ein Importfehler angezeigt: {Datei "C: \ Python33 \ lib \ site-packages \ slate-0.3-py3.3.egg \ slate_ init_ .py", Zeile 48, in <Modul> ImportError: Name PDF kann nicht importiert werden} Aber die PDF-Klasse ist da! Wissen Sie, wie man das löst?
Juankysmith
Nein, das klingt sehr seltsam. Haben Sie die Abhängigkeiten?
Tim McNamara
Normalerweise erhalte ich Nachrichten über verpasste Abhängigkeiten. In diesem Fall erhalte ich die klassische Nachricht "Schieferdatei importieren" C: \ Python33 \ lib \ site-packages \ slate-0.3-py3.3.egg \ slate_ init_ .py ", Zeile 48 , in <Modul> ImportError: Name PDF kann nicht importiert werden "
Juankysmith
Slate 0.3 erfordert pdfminer 20110515, gemäß dieser GitHub-Ausgabe
jabbett
6
Dieses Paket wird nicht mehr gepflegt. Verwenden Sie es nicht. Sie können es nicht einmal in Python 3.5
Sivasubramaniam Arunachalam
9

Ich musste eine bestimmte PDF-Datei innerhalb eines Python-Moduls in einfachen Text konvertieren. Ich habe PDFMiner 20110515 verwendet, nachdem ich das Tool pdf2txt.py gelesen hatte , habe ich dieses einfache Snippet geschrieben:

from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, process_pdf
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams

def to_txt(pdf_path):
    input_ = file(pdf_path, 'rb')
    output = StringIO()

    manager = PDFResourceManager()
    converter = TextConverter(manager, output, laparams=LAParams())
    process_pdf(manager, converter, input_)

    return output.getvalue() 
Gonz
quelle
1
def to_txt (pdf_path):
Cătălin George Feștilă
Wenn ich nur eine bestimmte Anzahl von Seiten konvertieren wollte, wie würde ich das mit diesem Code machen?
Psychok7
@ psychok7 Haben Sie versucht, das Tool pdf2txt zu verwenden? Es scheint diese Funktion in der aktuellen Version mit dem Flag -p zu unterstützen. Die Implementierung scheint einfach zu folgen und sollte auch leicht anzupassen sein: github.com/euske/pdfminer/blob/master/tools/pdf2txt.py Hoffe, es hilft! :)
Gonz
1
Danke @gonz, ich habe alles versucht, aber Ihre Lösung hat sich als perfekt für mich herausgestellt. Ausgabe mit Leerzeichen :)
Lazarus
pdf2txt.py ist hier für mich installiert:C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
Die rote Erbse
6

Umnutzung des mit pdfminer gelieferten Codes pdf2txt.py; Sie können eine Funktion erstellen, die einen Pfad zum PDF nimmt. Optional ein Outtype (txt | html | xml | tag) und Optionen wie die Befehlszeile pdf2txt {'-o': '/path/to/outfile.txt' ...}. Standardmäßig können Sie Folgendes aufrufen:

convert_pdf(path)

Es wird eine Textdatei erstellt, ein Geschwister im Dateisystem zum Original-PDF.

def convert_pdf(path, outtype='txt', opts={}):
    import sys
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter, process_pdf
    from pdfminer.converter import XMLConverter, HTMLConverter, TextConverter, TagExtractor
    from pdfminer.layout import LAParams
    from pdfminer.pdfparser import PDFDocument, PDFParser
    from pdfminer.pdfdevice import PDFDevice
    from pdfminer.cmapdb import CMapDB

    outfile = path[:-3] + outtype
    outdir = '/'.join(path.split('/')[:-1])

    debug = 0
    # input option
    password = ''
    pagenos = set()
    maxpages = 0
    # output option
    codec = 'utf-8'
    pageno = 1
    scale = 1
    showpageno = True
    laparams = LAParams()
    for (k, v) in opts:
        if k == '-d': debug += 1
        elif k == '-p': pagenos.update( int(x)-1 for x in v.split(',') )
        elif k == '-m': maxpages = int(v)
        elif k == '-P': password = v
        elif k == '-o': outfile = v
        elif k == '-n': laparams = None
        elif k == '-A': laparams.all_texts = True
        elif k == '-D': laparams.writing_mode = v
        elif k == '-M': laparams.char_margin = float(v)
        elif k == '-L': laparams.line_margin = float(v)
        elif k == '-W': laparams.word_margin = float(v)
        elif k == '-O': outdir = v
        elif k == '-t': outtype = v
        elif k == '-c': codec = v
        elif k == '-s': scale = float(v)
    #
    CMapDB.debug = debug
    PDFResourceManager.debug = debug
    PDFDocument.debug = debug
    PDFParser.debug = debug
    PDFPageInterpreter.debug = debug
    PDFDevice.debug = debug
    #
    rsrcmgr = PDFResourceManager()
    if not outtype:
        outtype = 'txt'
        if outfile:
            if outfile.endswith('.htm') or outfile.endswith('.html'):
                outtype = 'html'
            elif outfile.endswith('.xml'):
                outtype = 'xml'
            elif outfile.endswith('.tag'):
                outtype = 'tag'
    if outfile:
        outfp = file(outfile, 'w')
    else:
        outfp = sys.stdout
    if outtype == 'txt':
        device = TextConverter(rsrcmgr, outfp, codec=codec, laparams=laparams)
    elif outtype == 'xml':
        device = XMLConverter(rsrcmgr, outfp, codec=codec, laparams=laparams, outdir=outdir)
    elif outtype == 'html':
        device = HTMLConverter(rsrcmgr, outfp, codec=codec, scale=scale, laparams=laparams, outdir=outdir)
    elif outtype == 'tag':
        device = TagExtractor(rsrcmgr, outfp, codec=codec)
    else:
        return usage()

    fp = file(path, 'rb')
    process_pdf(rsrcmgr, device, fp, pagenos, maxpages=maxpages, password=password)
    fp.close()
    device.close()

    outfp.close()
    return
Skylar Saveland
quelle
1

PDFminer gab mir vielleicht eine Zeile [Seite 1 von 7 ...] auf jeder Seite einer PDF-Datei, die ich damit ausprobiert habe.

Die beste Antwort, die ich bisher habe, ist pdftoipe oder der C ++ - Code, der auf Xpdf basiert.

Siehe meine Frage, wie die Ausgabe von pdftoipe aussieht.

Sphäreinabox
quelle
1

Zusätzlich gibt es PDFTextStream , eine kommerzielle Java-Bibliothek, die auch von Python aus verwendet werden kann.

msanders
quelle
1

Ich habe verwendet pdftohtmlmit dem -xmlArgument, lesen Sie das Ergebnis mit subprocess.Popen(), das Ihnen x coord, y - Koordinaten zum Runterladen, Breite, Höhe und Schriftart, jeder Schnipsel des Textes im pdf. Ich denke, das ist es, was 'evince' wahrscheinlich auch verwendet, weil die gleichen Fehlermeldungen ausgegeben werden.

Wenn Sie Säulendaten verarbeiten müssen, wird dies etwas komplizierter, da Sie einen Algorithmus erfinden müssen, der zu Ihrer PDF-Datei passt. Das Problem ist, dass die Programme, die PDF-Dateien erstellen, den Text nicht unbedingt in einem logischen Format auslegen. Sie können einfache Sortieralgorithmen ausprobieren und es funktioniert manchmal, aber es kann kleine "Nachzügler" und "Streuner" geben, Textteile, die nicht in der Reihenfolge angeordnet werden, in der Sie sie erwartet haben. Man muss also kreativ werden.

Ich brauchte ungefähr 5 Stunden, um eines für die PDFs herauszufinden, an denen ich arbeitete. Aber jetzt funktioniert es ziemlich gut. Viel Glück.

Decora
quelle