Python-Modul zum konvertieren von PDF zu text [geschlossen]
-
09-06-2019 - |
Frage
Welche sind die besten Python Module konvertieren von PDF-Dateien in text?
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