PDF를 텍스트로 변환하는 Python 모듈
PDF 파일을 텍스트로 변환하는 가장 좋은 Python 모듈은 무엇입니까?
PDFMiner를 사용해보십시오 . PDF 파일에서 HTML, SGML 또는 "Tagged PDF"형식으로 텍스트를 추출 할 수 있습니다.
태그가 지정된 PDF 형식이 가장 깔끔한 것으로 보이며 XML 태그를 제거하면 텍스트 만 남습니다.
Python 3 버전은 다음에서 사용할 수 있습니다.
PDFMiner의 이후 패키지가 변경되었습니다 codeape을 기록했다.
편집 (다시) :
PDFMiner가 버전에서 다시 업데이트되었습니다 20100213
다음과 같이 설치 한 버전을 확인할 수 있습니다.
>>> import pdfminer
>>> pdfminer.__version__
'20100213'
다음은 업데이트 된 버전입니다 (변경 / 추가 한 내용에 대한 설명 포함).
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()
편집 (다시) :
여기에서 최신 버전 업데이트입니다 pypi는 , 20100619p1
. 간단히 말해서 LAParams 인스턴스를 CsvConverter 생성자 로 대체 LTTextItem
하여 LTChar
전달했습니다.
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()
편집 (한 번 더) :
버전에 맞게 업데이트되었습니다 20110515
(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()
이러한 솔루션에 대해 최신 버전의 PDFMiner를 지원하지 않으므로 PDFMiner를 사용하여 pdf 텍스트를 반환하는 간단한 솔루션을 작성했습니다. 가져 오기 오류가 발생하는 사람들에게 효과적입니다.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])
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 파이썬에서 호출 할 수있는 오픈 소스 프로그램 (Xpdf의 일부) (요청한 것이 아니라 유용 할 수 있음). 문제없이 사용했습니다. Google은 Google 데스크톱에서 사용한다고 생각합니다.
pyPDF 는 잘 작동합니다 (잘 구성된 PDF로 작업하고 있다고 가정). 공백이있는 텍스트 만 있으면 다음을 수행 할 수 있습니다.
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
메타 데이터, 이미지 데이터 등에 쉽게 액세스 할 수 있습니다.
extractText 코드 주석의 주석 :
컨텐츠 스트림에 제공된 순서대로 모든 텍스트 드로잉 명령을 찾고 텍스트를 추출하십시오. 일부 PDF 파일에는 적합하지만 사용 된 생성기에 따라 다른 파일에는 적합하지 않습니다. 이것은 앞으로 개선 될 것입니다. 이 기능이 더 정교 해지면 변경 될 것이므로이 기능에서 나오는 텍스트 순서에 의존하지 마십시오.
이것이 문제인지 여부는 텍스트로 수행하는 작업에 따라 다릅니다 (예 : 순서가 중요하지 않거나 괜찮거나 생성기가 표시되는 순서대로 스트림에 텍스트를 추가하면 괜찮습니다) . 매일 문제없이 pyPdf 추출 코드가 있습니다.
pdfminer를 라이브러리로 쉽게 사용할 수도 있습니다. pdf의 컨텐츠 모델에 액세스 할 수 있으며 고유 한 텍스트 추출을 작성할 수 있습니다. 아래 코드를 사용하여 PDF 내용을 세미콜론으로 구분 된 텍스트로 변환하기 위해이 작업을 수행했습니다.
이 함수는 단순히 y 및 x 좌표에 따라 TextItem 내용 객체를 정렬하고 하나의 텍스트 줄과 동일한 y 좌표를 가진 항목을 출력하여 같은 줄의 객체를 ';' 문자.
이 방법을 사용하면 다른 도구로는 더 이상 구문 분석에 적합한 내용을 추출 할 수없는 pdf에서 텍스트를 추출 할 수있었습니다. 내가 시도한 다른 도구로는 pdftotext, ps2ascii 및 온라인 도구 pdftextonline.com이 있습니다.
pdfminer는 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()
업데이트 :
위의 코드는 이전 버전의 API에 대해 작성되었습니다. 아래 내 의견을 참조하십시오.
slate
라이브러리에서 PDFMiner를 사용하는 것이 매우 간단한 프로젝트입니다.
>>> with open('example.pdf') as f:
... doc = slate.PDF(f)
...
>>> doc
[..., ..., ...]
>>> doc[1]
'Text from page 2...'
파이썬 모듈 내에서 특정 PDF를 일반 텍스트로 변환해야했습니다. pdf2txt.py 도구를 읽은 후 PDFMiner 20110515를 사용 했습니다. 이 간단한 스 니펫을 작성했습니다.
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()
pdfminer와 함께 제공되는 pdf2txt.py 코드를 대체합니다. pdf에 대한 경로를 취하는 기능을 만들 수 있습니다. 선택적으로 출력 형식 (txt | html | xml | tag)이며 명령 줄 pdf2txt { '-o': '/path/to/outfile.txt'...}와 같이 선택합니다. 기본적으로 다음을 호출 할 수 있습니다.
convert_pdf(path)
파일 시스템에서 원본 pdf와 같은 텍스트 파일이 생성됩니다.
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는 제가 시도한 pdf 파일의 모든 페이지에서 한 줄 [7/1 페이지 ...]을 줄 수도있었습니다.
내가 지금까지 가장 좋은 대답은 pdftoipe 또는 Xpdf를 기반으로하는 C ++ 코드입니다.
pdftoipe의 출력 결과에 대한 내 질문 을 참조하십시오 .
또한 파이썬에서도 사용할 수있는 상용 Java 라이브러리 인 PDFTextStream 이 있습니다.
나는 인수 pdftohtml
와 함께 사용 -xml
하고을 사용 하여 결과를 읽습니다 .pdf subprocess.Popen()
의 모든 텍스트 조각 의 x 좌표, y 좌표, 너비, 높이 및 글꼴 을 제공합니다. 나는 같은 오류 메시지가 나오기 때문에 아마도 '확실한'것이 아마도 사용하는 것이라고 생각합니다.
컬럼 데이터를 처리해야하는 경우 pdf 파일에 적합한 알고리즘을 발명해야하므로 약간 더 복잡해집니다. 문제는 PDF 파일을 만드는 프로그램이 텍스트를 논리적 형식으로 반드시 배치 할 필요는 없다는 것입니다. 간단한 정렬 알고리즘을 시도해 볼 수 있으며 때때로 작동하지만 생각한 순서대로 배치되지 않은 텍스트 인 '고글 거림'과 '떨림'이 거의 없을 수 있습니다. 따라서 창의력을 발휘해야합니다.
내가 작업하고 있던 pdf 파일 중 하나를 알아내는 데 약 5 시간이 걸렸습니다. 그러나 지금은 꽤 잘 작동합니다. 행운을 빕니다.
오늘 그 솔루션을 찾았습니다. 나를 위해 잘 작동합니다. PDF 페이지를 PNG 이미지로 렌더링 http://www.swftools.org/gfx_tutorial.html
참고 URL : https://stackoverflow.com/questions/25665/python-module-for-converting-pdf-to-text
'Programing' 카테고리의 다른 글
WCF와 ASMX 웹 서비스의 차이점은 무엇입니까? (0) | 2020.02.27 |
---|---|
SQLAlchemy : flush ()와 commit ()의 차이점은 무엇입니까? (0) | 2020.02.27 |
Node.js가있는 MySQL (0) | 2020.02.27 |
Express.js-app.listen 및 server.listen (0) | 2020.02.27 |
swift는 String에 트림 방법이 있습니까? (0) | 2020.02.26 |