Apakah ada modul python untuk mengkonversi file PDF menjadi teks? Saya mencoba sepotong kode yang ditemukan di Activestate yang menggunakan pypdf tetapi teks yang dihasilkan tidak memiliki ruang di antara dan tidak ada gunanya.
Apakah ada modul python untuk mengkonversi file PDF menjadi teks? Saya mencoba sepotong kode yang ditemukan di Activestate yang menggunakan pypdf tetapi teks yang dihasilkan tidak memiliki ruang di antara dan tidak ada gunanya.
Jawaban:
Coba PDFMiner . Itu dapat mengekstraksi teks dari file PDF sebagai format HTML, SGML atau "Tagged PDF".
Format Tagged PDF tampaknya paling bersih, dan menghapus tag XML hanya meninggalkan teks kosong.
Versi Python 3 tersedia di bawah:
The PDFMiner paket telah berubah sejak codeape diposting.
EDIT (lagi):
PDFMiner telah diperbarui lagi dalam versi 20100213
Anda dapat memeriksa versi yang telah Anda instal dengan yang berikut:
>>> import pdfminer
>>> pdfminer.__version__
'20100213'
Ini versi terbaru (dengan komentar tentang apa yang saya ubah / tambahkan):
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 (lagi):
Berikut ini adalah update untuk versi terbaru di pypi , 20100619p1
. Singkatnya saya diganti LTTextItem
dengan LTChar
dan melewati instance LAParams ke konstruktor CsvConverter.
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()
EDIT (sekali lagi):
Diperbarui untuk versi 20110515
(terima kasih kepada 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()
LTTextItem
menjadi LTChar
. unixuser.org/~euske/python/pdfminer/index.html#changes
20110515
per komentar Anda.
Karena tidak ada solusi ini yang mendukung versi PDFMiner terbaru, saya menulis solusi sederhana yang akan mengembalikan teks pdf menggunakan PDFMiner. Ini akan bekerja untuk mereka yang mendapatkan kesalahan imporprocess_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])
Lihat kode di bawah ini yang berfungsi untuk 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])
python3
, selain tanda kurung jelas setelah print
perintah, kita harus mengganti file
perintah dengan open
dan mengimpor StringIO
dari paketio
Pdftotext Program open source (bagian dari Xpdf) yang dapat Anda panggil dari python (bukan apa yang Anda minta tetapi mungkin bermanfaat). Saya sudah menggunakannya tanpa masalah. Saya pikir google menggunakannya di google desktop.
-layout
opsi untuk menyimpan teks pada posisi yang sama seperti dalam PDF. Sekarang kalau saja saya bisa mencari cara untuk menyalurkan isi PDF ke dalamnya.
pdftotext
tampaknya bekerja dengan sangat baik, tetapi perlu argumen kedua yang merupakan tanda hubung, jika Anda ingin melihat hasilnya di stdout.
find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;
Secara default file yang dihasilkan mengambil nama asli dengan .txt
ekstensi.
pyPDF berfungsi dengan baik (dengan asumsi Anda bekerja dengan PDF yang dibuat dengan baik). Jika semua yang Anda inginkan adalah teks (dengan spasi), Anda bisa melakukannya:
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
Anda juga dapat dengan mudah mendapatkan akses ke metadata, data gambar, dan sebagainya.
Sebuah komentar dalam catatan kode extractText:
Temukan semua perintah menggambar teks, sesuai urutannya disediakan dalam aliran konten, dan ekstrak teks. Ini berfungsi baik untuk beberapa file PDF, tetapi buruk untuk yang lain, tergantung pada generator yang digunakan. Ini akan disempurnakan di masa mendatang. Jangan mengandalkan urutan teks yang keluar dari fungsi ini, karena akan berubah jika fungsi ini dibuat lebih canggih.
Apakah ini masalah atau tidak tergantung pada apa yang Anda lakukan dengan teks (mis. Jika urutannya tidak masalah, itu baik-baik saja, atau jika generator menambahkan teks ke aliran dalam urutan yang akan ditampilkan, itu baik-baik saja) . Saya memiliki kode ekstraksi pyPdf dalam penggunaan sehari-hari, tanpa masalah.
Anda juga dapat dengan mudah menggunakan pdfminer sebagai pustaka. Anda memiliki akses ke model konten pdf, dan dapat membuat ekstraksi teks Anda sendiri. Saya melakukan ini untuk mengkonversi konten pdf ke teks yang dipisahkan semi-colon, menggunakan kode di bawah ini.
Fungsi ini hanya mengurutkan objek konten TextItem sesuai dengan koordinat y dan x mereka, dan menampilkan item dengan koordinat y yang sama dengan satu baris teks, memisahkan objek pada baris yang sama dengan ';' karakter.
Dengan menggunakan pendekatan ini, saya dapat mengekstraksi teks dari pdf yang tidak ada alat lain yang dapat mengekstraksi konten yang cocok untuk parsing selanjutnya. Alat lain yang saya coba meliputi pdftotext, ps2ascii dan alat online pdftextonline.com.
pdfminer adalah alat yang sangat berharga untuk 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()
PEMBARUAN :
Kode di atas ditulis terhadap versi API yang lama, lihat komentar saya di bawah.
pdfminer
, bukan pdflib
). Saya sarankan Anda melihat sumber pdf2txt.py
dalam sumber PDFminer, kode di atas terinspirasi oleh versi lama file itu.
slate
adalah proyek yang membuatnya sangat mudah untuk menggunakan PDFMiner dari perpustakaan:
>>> with open('example.pdf') as f:
... doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'
Saya perlu mengkonversi PDF tertentu ke teks biasa dalam modul python. Saya menggunakan PDFMiner 20110515, setelah membaca alat pdf2txt.py mereka, saya menulis cuplikan sederhana ini:
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()
C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
Repurposing kode pdf2txt.py yang datang dengan pdfminer; Anda dapat membuat fungsi yang akan mengambil jalur ke pdf; opsional, outtype (txt | html | xml | tag) dan memilih seperti commandline pdf2txt {'-o': '/path/to/outfile.txt' ...}. Secara default, Anda dapat menelepon:
convert_pdf(path)
File teks akan dibuat, saudara pada sistem file ke pdf asli.
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 memberi saya mungkin satu baris [halaman 1 dari 7 ...] pada setiap halaman file pdf yang saya coba.
Jawaban terbaik yang saya miliki sejauh ini adalah pdftoipe, atau kode c ++ didasarkan pada Xpdf.
lihat pertanyaan saya untuk seperti apa output dari pdftoipe.
Selain itu ada PDFTextStream yang merupakan perpustakaan Java komersial yang juga dapat digunakan dari Python.
Saya telah menggunakan pdftohtml
dengan -xml
argumen, membaca hasil dengan subprocess.Popen()
, yang akan memberikan x Coord, y Coord, lebar, tinggi, dan font, setiap potongan teks di pdf. Saya pikir inilah yang mungkin digunakan oleh 'evince' karena pesan kesalahan yang sama muncul.
Jika Anda perlu memproses data berbentuk kolom, itu akan menjadi sedikit lebih rumit karena Anda harus menemukan algoritma yang sesuai dengan file pdf Anda. Masalahnya adalah bahwa program-program yang membuat file PDF tidak benar-benar menata teks dalam format logis apa pun. Anda dapat mencoba algoritme pengurutan sederhana dan kadang-kadang berfungsi, tetapi mungkin ada sedikit 'orang yang tersesat' dan 'tersesat', potongan-potongan teks yang tidak dimasukkan ke dalam urutan yang Anda pikir akan dilakukan. Jadi, Anda harus kreatif.
Butuh waktu sekitar 5 jam untuk mencari satu untuk pdf yang sedang saya kerjakan. Tapi itu bekerja dengan cukup baik sekarang. Semoga berhasil.
Menemukan solusi itu hari ini. Bekerja bagus untukku. Bahkan merender halaman PDF ke gambar PNG. http://www.swftools.org/gfx_tutorial.html