Frage

Welche sind die besten Python Module konvertieren von PDF-Dateien in text?

War es hilfreich?

Lösung

Versuchen Sie es PDFMiner.Es kann extrahieren von text aus PDF-Dateien wie HTML, SGML oder "Tagged PDF" - format.

In der Tagged-PDF-format scheint die sauberste, und entfernen Sie die XML-tags gibt es nur den nackten text.

Ein Python-3-version ist verfügbar unter:

Andere Tipps

Die PDFMiner Paket hat sich verändert, seit codeape geschrieben.

EDIT (again):

PDFMiner wurde wieder aktualisiert version 20100213

Sie können überprüfen Sie die version, die Sie installiert haben, mit dem folgenden:

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

Hier ist die aktualisierte version (mit Kommentare, was ich geändert/Hinzugefügt):

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()

Edit (noch einmal):

Hier ist ein update für die neueste version pypi, 20100619p1.Kurz gesagt, ich ersetzt LTTextItem mit LTChar und übergeben Sie eine Instanz von LAParams der 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 (one more time):

Aktualisiert version 20110515 (Dank 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()

Da keiner für diese Lösungen unterstützen die neueste version von PDFMiner ich schrieb eine einfache Lösung, den text wieder von einem pdf-Dokument mit PDFMiner.Dies funktioniert für diejenigen, die importieren-Fehler mit process_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 unten code funktioniert für Python 3:

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])  

Pdftotext Ein open-source-Programm, (Teil von Xpdf), die Sie aufrufen von python (nicht das, was Sie gefragt, aber könnte nützlich sein).Ich habe es mit keine Probleme.Ich denke, google wird es in den google-desktop.

pyPDF funktioniert einwandfrei (vorausgesetzt, Sie arbeiten mit gut geformter PDF-Dateien).Wenn alle Sie wollen, ist der text (mit Leerzeichen), können Sie einfach tun:

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

Sie können auch leicht erhalten Zugang zu den Metadaten, Bild, Daten, und so weiter.

Ein Kommentar in der extractText code Anmerkungen:

Suchen Sie alle text zeichnen Befehle in die Reihenfolge, wie Sie sind zur Verfügung gestellt in die content-stream, und extrahieren Sie den text.Dies funktioniert gut für einige PDF-Dateien, aber schlecht für die anderen, je nach der generator verwendet.Dieser wird raffiniert in der Zukunft.Verlassen Sie sich nicht auf die Reihenfolge der text aus diesem Funktion, wie es wird sich ändern, wenn Sie diese Funktion komplexer.

Ob oder nicht, dies ist ein problem, hängt davon ab, was Sie tun, mit text (z.B.wenn die Reihenfolge spielt keine Rolle, es ist in Ordnung, oder, wenn der generator fügt text hinzu, um den Strom in der Reihenfolge angezeigt werden, es ist in Ordnung).Ich habe pyPdf Extraktion code im täglichen Einsatz, ohne Probleme.

Sie können auch ganz leicht verwenden, pdfminer wie eine Bibliothek.Sie haben Zugang zu den pdf-Inhalt, Modell und können erstellen Sie Ihre eigenen text-Extraktion.Ich Tat dies, um konvertieren von pdf-Inhalten zu semi-colon separated text, mit dem code unten.

Die Funktion einfach sortiert die TextItem content-Objekte nach Ihren y-und x-Koordinaten und Ausgänge Elemente mit der gleichen y-Koordinate als eine Textzeile, indem Sie die Objekte auf die gleiche Zeile, die mit '; ' - Zeichen.

Mit diesem Ansatz, ich war in der Lage, zum extrahieren von text aus einer pdf-Datei, kein anderes tool war in der Lage, zum extrahieren von Inhalten geeignet für die weitere Analyse aus.Andere Werkzeuge, die ich versuchte gehören 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 geschrieben gegen eine alte version der API, siehe mein Kommentar unten.

slate ist ein Projekt, das macht es sehr einfach zu bedienen PDFMiner aus der Bibliothek:

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

Ich brauchte, um zu konvertieren, eine bestimmte PDF-text in ein python-Modul.Ich verwendet PDFMiner 20110515 Sie nach dem Lesen durch Ihre pdf2txt.py Werkzeug, das ich schrieb dieses einfache snippet:

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() 

Wiederverwertung pdf2txt.py code, dass kommt mit pdfminer;Sie können eine Funktion, die einen Pfad zu dem pdf;Optional ist auch ein outtype (txt|html - |xml - |tag) und entscheidet sich, wie der commandline-pdf2txt {'-o':'/path/to/outfile.txt' ...}.Standardmäßig können Sie anrufen:

convert_pdf(path)

Eine text-Datei erstellt werden, ein Geschwisterchen auf das Dateisystem, um die ursprüngliche pdf-Datei.

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

PDFminer gab Sie mir vielleicht eine Zeile [Seite 1 von 7...] auf jeder Seite der pdf-Datei habe ich versucht mit ihm.

Die beste Antwort, die ich habe, so weit ist pdftoipe, oder der c++ - code basiert auf Xpdf.

finden meine Frage für das, was die Ausgabe von pdftoipe aussieht.

Zusätzlich gibt es PDFTextStream was ist eine kommerzielle Java-Bibliothek, die können auch verwendet werden, aus Python.

Ich habe verwendet pdftohtml mit der -xml argument, Lesen Sie das Ergebnis mit subprocess.Popen(),, dass wird geben Sie x coord, y coord, Breite, Höhe, schriftart und jeden snippet der text in der pdf-Datei.Ich denke, das ist es, was 'evince' verwendet wahrscheinlich auch, weil die gleichen Fehlermeldungen auszuspucken.

Wenn Sie müssen Prozess, säulenartigen Daten, wird es etwas komplizierter, als Sie zu erfinden einen Algorithmus, der Ihnen am besten pdf-Datei.Das problem ist, dass die Programme, die PDF-Dateien nicht wirklich unbedingt Layout den text in einer beliebigen logischen format.Sie können versuchen, einfache algorithmen zur Sortierung und es funktioniert manchmal, aber es kann kaum ein 'Nachzügler' und 'Streuner', text-Teile, die nicht bekommen, legen Sie in der Reihenfolge, die Sie dachten, Sie würden.So haben Sie, um kreativ zu werden.

Es dauerte ungefähr 5 Stunden, um herauszufinden, eine für das pdf das ich arbeiten war.Aber es funktioniert ziemlich gut jetzt.Viel Glück.

Gefunden, dass die heutige Lösung.Funktioniert großartig für mich.Auch das Rendern von PDF-Seiten in PNG-Bilder.http://www.swftools.org/gfx_tutorial.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top