[python] PDF를 텍스트로 변환하는 Python 모듈 [닫기]

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()


답변

이러한 솔루션에 대해 최신 버전의 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 파일에는 적합하지만 다른 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...'