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.
Antworten
Zu viele Anzeigen?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.
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...'
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()
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
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.