PDF 파일을 텍스트로 변환하는 파이썬 모듈이 있습니까? pypdf를 사용하는 Activestate에서 발견 된 한 가지 코드를 시도했지만 생성 된 텍스트 사이에 공백이없고 사용되지 않았습니다.
PDF 파일을 텍스트로 변환하는 파이썬 모듈이 있습니까? pypdf를 사용하는 Activestate에서 발견 된 한 가지 코드를 시도했지만 생성 된 텍스트 사이에 공백이없고 사용되지 않았습니다.
답변:
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()
LTTextItem
에 LTChar
. unixuser.org/~euske/python/pdfminer/index.html#changes
20110515
귀하의 의견에 따라 버전에 대한 답변에 다른 섹션을 추가했습니다 .
이러한 솔루션에 대해 최신 버전의 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])
python3
, print
명령 뒤에 명백한 괄호 외에 file
명령을 패키지로 open
StringIO
io
Pdftotext 파이썬에서 호출 할 수있는 오픈 소스 프로그램 (Xpdf의 일부) (요청한 것이 아니라 유용 할 수 있음). 문제없이 사용했습니다. Google은 Google 데스크톱에서 사용한다고 생각합니다.
-layout
PDF에있는 것과 동일한 위치에 텍스트를 유지 하는 옵션 과 함께 여기에 나열된 도구 중 가장 유용한 것 같습니다 . 이제 PDF의 내용을 PDF로 파이프하는 방법을 알아낼 수 있다면.
pdftotext
stdout에서 결과를 보려면 하이픈 인 두 번째 인수가 필요합니다.
find . -iname "*.pdf" -exec pdftotext -enc UTF-8 -eol unix -raw {} \;
기본적으로 생성 된 파일의 .txt
확장자 는 원래 이름입니다 .
pyPDF 는 잘 작동합니다 (잘 구성된 PDF로 작업하고 있다고 가정). 공백이있는 텍스트 만 있으면 다음을 수행 할 수 있습니다.
import pyPdf
pdf = pyPdf.PdfFileReader(open(filename, "rb"))
for page in pdf.pages:
print page.extractText()
메타 데이터, 이미지 데이터 등에 쉽게 액세스 할 수 있습니다.
extractText 코드 주석의 주석 :
컨텐츠 스트림에 제공된 순서대로 모든 텍스트 드로잉 명령을 찾고 텍스트를 추출하십시오. 이것은 사용되는 생성기에 따라 일부 PDF 파일에는 적합하지만 다른 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에 대해 작성되었습니다. 아래 내 의견을 참조하십시오.
pdfminer
아닌 pdflib
). pdf2txt.py
PDFminer 소스 의 소스를 살펴볼 것을 제안합니다. 위의 코드는 해당 파일의 이전 버전에서 영감을 얻은 것입니다.
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()
C:\Python27\Scripts\pdfminer\tools\pdf2txt.py
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
또한 파이썬에서도 사용할 수있는 상용 Java 라이브러리 인 PDFTextStream 이 있습니다.
나는 인수 pdftohtml
와 함께 사용 -xml
하고을 사용 하여 결과를 읽습니다 .pdf subprocess.Popen()
의 모든 텍스트 조각 의 x 좌표, y 좌표, 너비, 높이 및 글꼴 을 제공합니다. 나는 같은 오류 메시지가 나오기 때문에 아마도 '확실한'것도 아마도 사용하는 것이라고 생각합니다.
컬럼 데이터를 처리해야하는 경우 pdf 파일에 적합한 알고리즘을 발명해야하므로 약간 더 복잡해집니다. 문제는 PDF 파일을 만드는 프로그램이 텍스트를 논리적 형식으로 반드시 배치 할 필요는 없다는 것입니다. 간단한 정렬 알고리즘을 시도해 볼 수 있으며 때때로 작동하지만 생각한 순서대로 배치되지 않은 텍스트 인 '고글 거림'과 '떨림'이 거의 없을 수 있습니다. 따라서 창의력을 발휘해야합니다.
내가 작업하고 있던 pdf 파일 중 하나를 파악하는 데 약 5 시간이 걸렸습니다. 그러나 지금은 잘 작동합니다. 행운을 빕니다.
오늘 그 솔루션을 찾았습니다. 나를 위해 잘 작동합니다. PDF 페이지를 PNG 이미지로 렌더링 http://www.swftools.org/gfx_tutorial.html