419 Stimmen

Python-Modul zur Konvertierung von PDF in Text

Gibt es ein Python-Modul, um PDF-Dateien in Text zu konvertieren? Ich habe versucht ein Stück Code in Activestate gefunden, das pypdf verwendet, aber der erzeugte Text hatte keine Leerzeichen dazwischen und war unbrauchbar.

21voto

codeape Punkte 93809

Sie können pdfminer auch ganz einfach als Bibliothek verwenden. Sie haben Zugriff auf das pdf-Inhaltsmodell und können Ihre eigene Textextraktion erstellen. Ich habe dies getan, um pdf-Inhalte in durch Semikolon getrennten Text zu konvertieren, indem ich den folgenden Code verwendet habe.

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

Mit diesem Ansatz konnte ich Text aus einer PDF-Datei extrahieren, aus der kein anderes Tool Inhalte extrahieren konnte, die für eine weitere Analyse 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 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 ist für eine alte Version der API geschrieben, siehe meinen Kommentar unten.

17voto

Tim McNamara Punkte 17453

slate ist ein Projekt, das es sehr einfach macht, PDFMiner aus einer Bibliothek heraus zu verwenden:

>>> with open('example.pdf') as f:
...    doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'

9voto

gonz Punkte 4966

Ich musste ein bestimmtes PDF in einem Python-Modul in einfachen Text umwandeln. Ich verwendete PDFMiner 20110515, nach dem Durchlesen ihrer pdf2txt.py Tool 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()

6voto

Skylar Saveland Punkte 10479

Wiederverwendung des pdf2txt.py-Codes, der mit pdfminer mitgeliefert wird; Sie können eine Funktion erstellen, die einen Pfad zum PDF, optional einen Outtype (txt|html|xml|tag) und Optionen wie die Kommandozeile pdf2txt {'-o': '/path/to/outfile.txt' ...} verwendet. Standardmäßig können Sie aufrufen:

convert_pdf(path)

Es wird eine Textdatei erstellt, die im Dateisystem ein Geschwisterchen der ursprünglichen PDF-Datei ist.

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

1voto

sphereinabox Punkte 846

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 gefunden habe, ist pdftoipe, oder der C++-Code, der auf Xpdf basiert.

véase meine Frage um zu sehen, wie die Ausgabe von pdftoipe aussieht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X