Có mô-đun python nào để chuyển đổi tập tin PDF thành văn bản không? Tôi đã thử một đoạn mã được tìm thấy trong Activestate sử dụng pypdf nhưng văn bản được tạo ra không có khoảng cách giữa và không sử dụng được.
Có mô-đun python nào để chuyển đổi tập tin PDF thành văn bản không? Tôi đã thử một đoạn mã được tìm thấy trong Activestate sử dụng pypdf nhưng văn bản được tạo ra không có khoảng cách giữa và không sử dụng được.
Câu trả lời:
Hãy thử PDFMiner . Nó có thể trích xuất văn bản từ các tệp PDF dưới dạng HTML, SGML hoặc định dạng "Tagged PDF".
Định dạng PDF được gắn thẻ có vẻ là sạch nhất và việc loại bỏ các thẻ XML chỉ để lại văn bản trống.
Phiên bản Python 3 có sẵn trong:
Các PDFMiner gói đã thay đổi kể từ codeape đăng.
EDIT (một lần nữa):
PDFMiner đã được cập nhật lại trong phiên bản 20100213
Bạn có thể kiểm tra phiên bản bạn đã cài đặt như sau:
>>> import pdfminer
>>> pdfminer.__version__
'20100213'
Đây là phiên bản cập nhật (có nhận xét về những gì tôi đã thay đổi / thêm):
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()
Chỉnh sửa (một lần nữa):
Đây là bản cập nhật cho phiên bản mới nhất bằng pypi , 20100619p1
. Nói tóm lại tôi đã thay thế LTTextItem
với LTChar
và thông qua một thể hiện của LAParams để các nhà xây dựng 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 (một lần nữa):
Đã cập nhật cho phiên bản 20110515
(nhờ 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
đến LTChar
. unixuser.org/~euske/python/pdfminer/index.html#changes
20110515
cho mỗi bình luận của bạn.
Vì không có giải pháp nào hỗ trợ phiên bản PDFMiner mới nhất, tôi đã viết một giải pháp đơn giản sẽ trả về văn bản của pdf bằng PDFMiner. Điều này sẽ làm việc cho những người đang nhận được lỗi nhập khẩu vớiprocess_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])
Xem mã dưới đây hoạt động cho 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
, bên cạnh các dấu ngoặc đơn rõ ràng sau print
lệnh, người ta phải thay thế file
lệnh bằng open
và nhập StringIO
từ góiio
Pdftotext Một chương trình mã nguồn mở (một phần của Xpdf) mà bạn có thể gọi từ python (không phải những gì bạn yêu cầu nhưng có thể hữu ích). Tôi đã sử dụng nó mà không có vấn đề. Tôi nghĩ rằng google sử dụng nó trong máy tính để bàn google.
-layout
tùy chọn giữ văn bản ở cùng vị trí như trong PDF. Bây giờ nếu tôi chỉ có thể tìm ra cách đưa nội dung của tệp PDF vào đó.
pdftotext
có vẻ hoạt động rất tốt, nhưng nó cần một đối số thứ hai là dấu gạch nối, nếu bạn muốn xem kết quả trên thiết bị xuất chuẩn.
find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;
Theo mặc định, các tệp được tạo có tên gốc với .txt
phần mở rộng.
pyPDF hoạt động tốt (giả sử rằng bạn đang làm việc với các tệp PDF được định dạng tốt). Nếu tất cả những gì bạn muốn là văn bản (có dấu cách), bạn có thể thực hiện:
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
Bạn cũng có thể dễ dàng truy cập vào siêu dữ liệu, dữ liệu hình ảnh, v.v.
Một nhận xét trong ghi chú mã trích xuất:
Xác định vị trí tất cả các lệnh vẽ văn bản, theo thứ tự chúng được cung cấp trong luồng nội dung và trích xuất văn bản. Điều này hoạt động tốt đối với một số tệp PDF, nhưng kém đối với các tệp khác, tùy thuộc vào trình tạo được sử dụng. Điều này sẽ được tinh chế trong tương lai. Không dựa vào thứ tự văn bản ra khỏi chức năng này, vì nó sẽ thay đổi nếu chức năng này được thực hiện tinh vi hơn.
Đây có phải là vấn đề hay không phụ thuộc vào những gì bạn đang làm với văn bản (ví dụ: nếu đơn hàng không thành vấn đề, nó ổn hoặc nếu trình tạo thêm văn bản vào luồng theo thứ tự nó sẽ được hiển thị, thì tốt thôi) . Tôi có mã trích xuất pyPdf trong sử dụng hàng ngày, không có vấn đề gì.
Bạn cũng có thể dễ dàng sử dụng pdfminer làm thư viện. Bạn có quyền truy cập vào mô hình nội dung của pdf và có thể tạo trích xuất văn bản của riêng bạn. Tôi đã làm điều này để chuyển đổi nội dung pdf thành văn bản tách dấu hai chấm, sử dụng mã dưới đây.
Hàm chỉ đơn giản sắp xếp các đối tượng nội dung TextItem theo tọa độ y và x của chúng và xuất ra các mục có cùng tọa độ y với một dòng văn bản, tách các đối tượng trên cùng một dòng với ';' nhân vật.
Sử dụng phương pháp này, tôi có thể trích xuất văn bản từ pdf mà không có công cụ nào khác có thể trích xuất nội dung phù hợp để phân tích cú pháp thêm. Các công cụ khác tôi đã thử bao gồm pdftotext, ps2ascii và công cụ trực tuyến pdftextonline.com.
pdfminer là một công cụ vô giá để quét pdf.
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()
CẬP NHẬT :
Mã ở trên được viết dựa trên phiên bản cũ của API, xem nhận xét của tôi bên dưới.
pdfminer
, không phải pdflib
). Tôi đề nghị bạn nên xem nguồn pdf2txt.py
trong nguồn PDFminer, đoạn mã trên được lấy cảm hứng từ phiên bản cũ của tệp đó.
slate
là một dự án giúp sử dụng PDFMiner từ thư viện rất đơn giản:
>>> with open('example.pdf') as f:
... doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'
Tôi cần chuyển đổi một tệp PDF cụ thể thành văn bản thuần túy trong mô-đun python. Tôi đã sử dụng PDFMiner 20110515, sau khi đọc qua công cụ pdf2txt.py của họ, tôi đã viết đoạn trích đơn giản này:
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
Tái sử dụng mã pdf2txt.py đi kèm với pdfminer; bạn có thể tạo một hàm sẽ đưa một đường dẫn đến pdf; tùy chọn, một loại outtype (txt | html | xml | tag) và hoạt động như dòng lệnh pdf2txt {'-o': '/path/to/outfile.txt' ...}. Theo mặc định, bạn có thể gọi:
convert_pdf(path)
Một tệp văn bản sẽ được tạo, anh chị em trên hệ thống tệp với pdf gốc.
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 đã cho tôi có lẽ một dòng [trang 1 trên 7 ...] trên mỗi trang của tệp pdf tôi đã thử với nó.
Câu trả lời tốt nhất tôi có cho đến nay là pdftoipe, hoặc mã c ++ dựa trên Xpdf.
xem câu hỏi của tôi để biết đầu ra của pdftoipe trông như thế nào.
Ngoài ra, còn có PDFTextStream , một thư viện Java thương mại cũng có thể được sử dụng từ Python.
Tôi đã sử dụng pdftohtml
với -xml
đối số, đọc kết quả với subprocess.Popen()
, nó sẽ cung cấp cho bạn tọa độ x, tọa độ y, chiều rộng, chiều cao và phông chữ của mỗi đoạn văn bản trong pdf. Tôi nghĩ rằng đây là những gì 'evince' có thể sử dụng vì các thông báo lỗi tương tự xuất hiện.
Nếu bạn cần xử lý dữ liệu cột, nó sẽ phức tạp hơn một chút vì bạn phải phát minh ra một thuật toán phù hợp với tệp pdf của mình. Vấn đề là các chương trình tạo tệp PDF không thực sự bố trí văn bản theo bất kỳ định dạng logic nào. Bạn có thể thử các thuật toán sắp xếp đơn giản và đôi khi nó hoạt động, nhưng có thể có một ít 'stragglers' và 'strays', các đoạn văn bản không được đặt theo thứ tự bạn nghĩ chúng sẽ làm. Vì vậy, bạn phải có được sáng tạo.
Tôi mất khoảng 5 giờ để tìm ra một bản pdf mà tôi đang làm việc. Nhưng nó hoạt động khá tốt bây giờ. Chúc may mắn.
Tìm thấy giải pháp đó ngày hôm nay. Làm việc tuyệt vời cho tôi. Thậm chí kết xuất các trang PDF thành hình ảnh PNG. http://www.swftools.org/gfx_tutorial.html