복붙노트

[PYTHON] PDF 파일에서 텍스트를 추출하는 방법은 무엇입니까?

PYTHON

PDF 파일에서 텍스트를 추출하는 방법은 무엇입니까?

파이썬을 사용하여이 PDF 파일에 포함 된 텍스트를 추출하려고합니다.

나는 PyPDF2 모듈을 사용하고 있으며 다음과 같은 스크립트를 가지고있다 :

import PyPDF2
pdf_file = open('sample.pdf')
read_pdf = PyPDF2.PdfFileReader(pdf_file)
number_of_pages = read_pdf.getNumPages()
page = read_pdf.getPage(0)
page_content = page.extractText()
print page_content

코드를 실행하면 PDF 문서에 포함 된 내용과 다른 다음 출력이 표시됩니다.

!"#$%#$%&%$&'()*%+,-%./01'*23%4
5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
%

PDF 문서에있는대로 텍스트를 추출하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.textract를 사용하십시오.

    textract를 사용하십시오.

    그것은 PDF를 포함하여 많은 종류의 파일을 지원합니다

    import textract
    text = textract.process("path/to/file.extension")
    
  2. ==============================

    2.이 코드를보십시오 :

    이 코드를보십시오 :

    import PyPDF2
    pdf_file = open('sample.pdf', 'rb')
    read_pdf = PyPDF2.PdfFileReader(pdf_file)
    number_of_pages = read_pdf.getNumPages()
    page = read_pdf.getPage(0)
    page_content = page.extractText()
    print page_content.encode('utf-8')
    

    출력은 다음과 같습니다.

    !"#$%#$%&%$&'()*%+,-%./01'*23%4
    5'%1$#26%3/%7/))/8%&)/26%8#3"%3"*%313/9#&)
    %
    

    동일한 코드를 사용하여 201308FCR.pdf에서 pdf를 읽으십시오. 출력은 정상입니다.

    그 문서는 이유를 설명합니다 :

    def extractText(self):
        """
        Locate all text drawing commands, in the order they are provided in the
        content stream, and extract the text.  This works well for some PDF
        files, but poorly for others, depending on the generator used.  This will
        be refined in the future.  Do not rely on the order of text coming out of
        this function, as it will change if this function is made more
        sophisticated.
        :return: a unicode string object.
        """
    
  3. ==============================

    3.파이썬 3.x와 윈도우에 사용할 간단한 솔루션을 찾고있었습니다. textract에서 지원하지 않는 것 같습니다. 불행한 일이지만, Windows / Python 3 Checkout에 대한 간단한 솔루션을 찾으려면 tika 패키지를 사용하십시오.

    파이썬 3.x와 윈도우에 사용할 간단한 솔루션을 찾고있었습니다. textract에서 지원하지 않는 것 같습니다. 불행한 일이지만, Windows / Python 3 Checkout에 대한 간단한 솔루션을 찾으려면 tika 패키지를 사용하십시오.

    from tika import parser
    
    raw = parser.from_file('sample.pdf')
    print(raw['content'])
    
  4. ==============================

    4.textpar (너무 많은 의존성이있는 것 같음)와 pypdf2 (테스트 한 pdfs에서 텍스트를 추출 할 수 없음) 및 tika (너무 느림)를 시도한 후에 xpdf에서 pdftotext를 사용하여 종료했습니다 (이미 다른 답변에서 제안 된대로) 방금 파이썬에서 바이너리를 직접 호출했습니다 (pdftotext에 경로를 적용해야 할 수도 있음).

    textpar (너무 많은 의존성이있는 것 같음)와 pypdf2 (테스트 한 pdfs에서 텍스트를 추출 할 수 없음) 및 tika (너무 느림)를 시도한 후에 xpdf에서 pdftotext를 사용하여 종료했습니다 (이미 다른 답변에서 제안 된대로) 방금 파이썬에서 바이너리를 직접 호출했습니다 (pdftotext에 경로를 적용해야 할 수도 있음).

    import os, subprocess
    SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
    args = ["/usr/local/bin/pdftotext",
            '-enc',
            'UTF-8',
            "{}/my-pdf.pdf".format(SCRIPT_DIR),
            '-']
    res = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output = res.stdout.decode('utf-8')
    

    pdftotext는 기본적으로 동일하지만 pdftotext는 / usr / local / bin에있는 반면 AWS 람다에서는 이것을 사용하고 현재 디렉토리에서 사용하려고합니다.

    Btw : 람다에서 이것을 사용하려면 바이너리와 의존성을 libstdc ++에 넣어 라. 람다 함수에 넣어야한다. 필자는 개인적으로 xpdf를 컴파일해야했습니다. 이것에 대한 지시가이 대답을 날려 버릴 것이므로 나는 그들을 내 개인 블로그에 올려 놓았다.

  5. ==============================

    5.pyPDF2가 텍스트 추출과 관련하여 여전히 여러 가지 문제가있는 것처럼 보이는 대신 xPDF 및 파생 툴을 사용하여 텍스트를 추출하는 것이 좋습니다.

    pyPDF2가 텍스트 추출과 관련하여 여전히 여러 가지 문제가있는 것처럼 보이는 대신 xPDF 및 파생 툴을 사용하여 텍스트를 추출하는 것이 좋습니다.

    긴 대답은 PDF 내에서 텍스트가 인코딩되는 방식이 다양하고 PDF 문자열 자체를 해독해야하는 경우 CMAP로 매핑해야 할 수 있다는 점입니다. 그런 다음 단어와 문자 사이의 거리를 분석해야 할 수도 있습니다.

    PDF가 손상된 경우 (즉, 올바른 텍스트를 표시하지만 가비지를 복사 할 때) 실제로 텍스트를 추출해야하는 경우 PDF를 ImageMagik을 사용하여 이미지로 변환 한 다음 Tesseract를 사용하여 이미지에서 텍스트를 가져 오는 것이 좋습니다 OCR 사용.

  6. ==============================

    6.아래의 코드는 Python 3의 질문에 대한 해결책입니다. 코드를 실행하기 전에, 여러분의 환경에 PyPDF2 라이브러리를 설치했는지 확인하십시오. 설치되어 있지 않은 경우 명령 프롬프트를 열고 다음 명령을 실행하십시오.

    아래의 코드는 Python 3의 질문에 대한 해결책입니다. 코드를 실행하기 전에, 여러분의 환경에 PyPDF2 라이브러리를 설치했는지 확인하십시오. 설치되어 있지 않은 경우 명령 프롬프트를 열고 다음 명령을 실행하십시오.

    pip3 install PyPDF2
    

    솔루션 코드 :

    import PyPDF2
    pdfFileObject = open('sample.pdf', 'rb')
    pdfReader = PyPDF2.PdfFileReader(pdfFileObject)
    count = pdfReader.numPages
    for i in range(count):
        page = pdfReader.getPage(i)
        print(page.extractText())
    
  7. ==============================

    7.PDFtoText를 사용할 수 있습니다. https://github.com/jalan/pdftotext

    PDFtoText를 사용할 수 있습니다. https://github.com/jalan/pdftotext

    PDF로 텍스트를 텍스트 형식으로 들여 쓰기 할 수 있습니다. 테이블이 있으면 중요하지 않습니다.

  8. ==============================

    8.다중 페이지 pdf는 아래 코드를 사용하여 개별 페이지 번호를 인수로 제공하는 대신 단일 스트레치로 텍스트로 추출 할 수 있습니다

    다중 페이지 pdf는 아래 코드를 사용하여 개별 페이지 번호를 인수로 제공하는 대신 단일 스트레치로 텍스트로 추출 할 수 있습니다

    import PyPDF2
    import collections
    pdf_file = open('samples.pdf', 'rb')
    read_pdf = PyPDF2.PdfFileReader(pdf_file)
    number_of_pages = read_pdf.getNumPages()
    c = collections.Counter(range(number_of_pages))
    for i in c:
       page = read_pdf.getPage(i)
       page_content = page.extractText()
       print page_content.encode('utf-8')
    
  9. ==============================

    9.이 작업을 수행하는 코드를 추가하고 있습니다. 그것은 나를 위해 잘 작동합니다 :

    이 작업을 수행하는 코드를 추가하고 있습니다. 그것은 나를 위해 잘 작동합니다 :

    # This works in python 3
    # required python packages
    # tabula-py==1.0.0
    # PyPDF2==1.26.0
    # Pillow==4.0.0
    # pdfminer.six==20170720
    
    import os
    import shutil
    import warnings
    from io import StringIO
    
    import requests
    import tabula
    from PIL import Image
    from PyPDF2 import PdfFileWriter, PdfFileReader
    from pdfminer.converter import TextConverter
    from pdfminer.layout import LAParams
    from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
    from pdfminer.pdfpage import PDFPage
    
    warnings.filterwarnings("ignore")
    
    
    def download_file(url):
        local_filename = url.split('/')[-1]
        local_filename = local_filename.replace("%20", "_")
        r = requests.get(url, stream=True)
        print(r)
        with open(local_filename, 'wb') as f:
            shutil.copyfileobj(r.raw, f)
    
        return local_filename
    
    
    class PDFExtractor():
        def __init__(self, url):
            self.url = url
    
        # Downloading File in local
        def break_pdf(self, filename, start_page=-1, end_page=-1):
            pdf_reader = PdfFileReader(open(filename, "rb"))
            # Reading each pdf one by one
            total_pages = pdf_reader.numPages
            if start_page == -1:
                start_page = 0
            elif start_page < 1 or start_page > total_pages:
                return "Start Page Selection Is Wrong"
            else:
                start_page = start_page - 1
    
            if end_page == -1:
                end_page = total_pages
            elif end_page < 1 or end_page > total_pages - 1:
                return "End Page Selection Is Wrong"
            else:
                end_page = end_page
    
            for i in range(start_page, end_page):
                output = PdfFileWriter()
                output.addPage(pdf_reader.getPage(i))
                with open(str(i + 1) + "_" + filename, "wb") as outputStream:
                    output.write(outputStream)
    
        def extract_text_algo_1(self, file):
            pdf_reader = PdfFileReader(open(file, 'rb'))
            # creating a page object
            pageObj = pdf_reader.getPage(0)
    
            # extracting extract_text from page
            text = pageObj.extractText()
            text = text.replace("\n", "").replace("\t", "")
            return text
    
        def extract_text_algo_2(self, file):
            pdfResourceManager = PDFResourceManager()
            retstr = StringIO()
            la_params = LAParams()
            device = TextConverter(pdfResourceManager, retstr, codec='utf-8', laparams=la_params)
            fp = open(file, 'rb')
            interpreter = PDFPageInterpreter(pdfResourceManager, device)
            password = ""
            max_pages = 0
            caching = True
            page_num = set()
    
            for page in PDFPage.get_pages(fp, page_num, maxpages=max_pages, password=password, caching=caching,
                                          check_extractable=True):
                interpreter.process_page(page)
    
            text = retstr.getvalue()
            text = text.replace("\t", "").replace("\n", "")
    
            fp.close()
            device.close()
            retstr.close()
            return text
    
        def extract_text(self, file):
            text1 = self.extract_text_algo_1(file)
            text2 = self.extract_text_algo_2(file)
    
            if len(text2) > len(str(text1)):
                return text2
            else:
                return text1
    
        def extarct_table(self, file):
    
            # Read pdf into DataFrame
            try:
                df = tabula.read_pdf(file, output_format="csv")
            except:
                print("Error Reading Table")
                return
    
            print("\nPrinting Table Content: \n", df)
            print("\nDone Printing Table Content\n")
    
        def tiff_header_for_CCITT(self, width, height, img_size, CCITT_group=4):
            tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h'
            return struct.pack(tiff_header_struct,
                               b'II',  # Byte order indication: Little indian
                               42,  # Version number (always 42)
                               8,  # Offset to first IFD
                               8,  # Number of tags in IFD
                               256, 4, 1, width,  # ImageWidth, LONG, 1, width
                               257, 4, 1, height,  # ImageLength, LONG, 1, lenght
                               258, 3, 1, 1,  # BitsPerSample, SHORT, 1, 1
                               259, 3, 1, CCITT_group,  # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding
                               262, 3, 1, 0,  # Threshholding, SHORT, 1, 0 = WhiteIsZero
                               273, 4, 1, struct.calcsize(tiff_header_struct),  # StripOffsets, LONG, 1, len of header
                               278, 4, 1, height,  # RowsPerStrip, LONG, 1, lenght
                               279, 4, 1, img_size,  # StripByteCounts, LONG, 1, size of extract_image
                               0  # last IFD
                               )
    
        def extract_image(self, filename):
            number = 1
            pdf_reader = PdfFileReader(open(filename, 'rb'))
    
            for i in range(0, pdf_reader.numPages):
    
                page = pdf_reader.getPage(i)
    
                try:
                    xObject = page['/Resources']['/XObject'].getObject()
                except:
                    print("No XObject Found")
                    return
    
                for obj in xObject:
    
                    try:
    
                        if xObject[obj]['/Subtype'] == '/Image':
                            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
                            data = xObject[obj]._data
                            if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                                mode = "RGB"
                            else:
                                mode = "P"
    
                            image_name = filename.split(".")[0] + str(number)
    
                            print(xObject[obj]['/Filter'])
    
                            if xObject[obj]['/Filter'] == '/FlateDecode':
                                data = xObject[obj].getData()
                                img = Image.frombytes(mode, size, data)
                                img.save(image_name + "_Flate.png")
                                # save_to_s3(imagename + "_Flate.png")
                                print("Image_Saved")
    
                                number += 1
                            elif xObject[obj]['/Filter'] == '/DCTDecode':
                                img = open(image_name + "_DCT.jpg", "wb")
                                img.write(data)
                                # save_to_s3(imagename + "_DCT.jpg")
                                img.close()
                                number += 1
                            elif xObject[obj]['/Filter'] == '/JPXDecode':
                                img = open(image_name + "_JPX.jp2", "wb")
                                img.write(data)
                                # save_to_s3(imagename + "_JPX.jp2")
                                img.close()
                                number += 1
                            elif xObject[obj]['/Filter'] == '/CCITTFaxDecode':
                                if xObject[obj]['/DecodeParms']['/K'] == -1:
                                    CCITT_group = 4
                                else:
                                    CCITT_group = 3
                                width = xObject[obj]['/Width']
                                height = xObject[obj]['/Height']
                                data = xObject[obj]._data  # sorry, getData() does not work for CCITTFaxDecode
                                img_size = len(data)
                                tiff_header = self.tiff_header_for_CCITT(width, height, img_size, CCITT_group)
                                img_name = image_name + '_CCITT.tiff'
                                with open(img_name, 'wb') as img_file:
                                    img_file.write(tiff_header + data)
    
                                # save_to_s3(img_name)
                                number += 1
                    except:
                        continue
    
            return number
    
        def read_pages(self, start_page=-1, end_page=-1):
    
            # Downloading file locally
            downloaded_file = download_file(self.url)
            print(downloaded_file)
    
            # breaking PDF into number of pages in diff pdf files
            self.break_pdf(downloaded_file, start_page, end_page)
    
            # creating a pdf reader object
            pdf_reader = PdfFileReader(open(downloaded_file, 'rb'))
    
            # Reading each pdf one by one
            total_pages = pdf_reader.numPages
    
            if start_page == -1:
                start_page = 0
            elif start_page < 1 or start_page > total_pages:
                return "Start Page Selection Is Wrong"
            else:
                start_page = start_page - 1
    
            if end_page == -1:
                end_page = total_pages
            elif end_page < 1 or end_page > total_pages - 1:
                return "End Page Selection Is Wrong"
            else:
                end_page = end_page
    
            for i in range(start_page, end_page):
                # creating a page based filename
                file = str(i + 1) + "_" + downloaded_file
    
                print("\nStarting to Read Page: ", i + 1, "\n -----------===-------------")
    
                file_text = self.extract_text(file)
                print(file_text)
                self.extract_image(file)
    
                self.extarct_table(file)
                os.remove(file)
                print("Stopped Reading Page: ", i + 1, "\n -----------===-------------")
    
            os.remove(downloaded_file)
    
    
    # I have tested on these 3 pdf files
    # url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Healthcare-January-2017.pdf"
    url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sample_Test.pdf"
    # url = "http://s3.amazonaws.com/NLP_Project/Original_Documents/Sazerac_FS_2017_06_30%20Annual.pdf"
    # creating the instance of class
    pdf_extractor = PDFExtractor(url)
    
    # Getting desired data out
    pdf_extractor.read_pages(15, 23)
    
  10. ==============================

    10.다음은 텍스트 추출을위한 가장 간단한 코드입니다

    다음은 텍스트 추출을위한 가장 간단한 코드입니다

    암호:

          # importing required modules
          import PyPDF2
    
          # creating a pdf file object
          pdfFileObj = open('filename.pdf', 'rb')
    
          # creating a pdf reader object
          pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
    
          # printing number of pages in pdf file
          print(pdfReader.numPages)
    
          # creating a page object
          pageObj = pdfReader.getPage(5)
    
          # extracting text from page
          print(pageObj.extractText())
    
          # closing the pdf file object
          pdfFileObj.close()
    
  11. ==============================

    11.어떤 경우에는 PyPDF2가 공백을 무시하고 결과 텍스트를 엉망으로 만들지 만 PyMuPDF를 사용하면 정말 만족 스럽습니다. 이 링크를 사용하여 자세한 정보를 얻을 수 있습니다.

    어떤 경우에는 PyPDF2가 공백을 무시하고 결과 텍스트를 엉망으로 만들지 만 PyMuPDF를 사용하면 정말 만족 스럽습니다. 이 링크를 사용하여 자세한 정보를 얻을 수 있습니다.

  12. ==============================

    12.여기에서 tika-app-xxx.jar (latest)를 다운로드 할 수 있습니다.

    여기에서 tika-app-xxx.jar (latest)를 다운로드 할 수 있습니다.

    그런 다음이 .jar 파일을 파이썬 스크립트 파일의 같은 폴더에 넣으십시오.

    그런 다음 스크립트에 다음 코드를 삽입하십시오.

    import os
    import os.path
    
    tika_dir=os.path.join(os.path.dirname(__file__),'<tika-app-xxx>.jar')
    
    def extract_pdf(source_pdf:str,target_txt:str):
        os.system('java -jar '+tika_dir+' -t {} > {}'.format(source_pdf,target_txt))
    

    의존성 감소. 단일 .jar 파일은 파이썬 패키지보다 관리하기 쉽습니다.

    멀티 포맷 지원. source_pdf 위치는 모든 종류의 문서 디렉토리 일 수 있습니다. (.doc, .html, .odt 등)

    최신 정보. tika-app.jar는 항상 tika python 패키지의 관련 버전보다 먼저 릴리스됩니다.

    안정된. PyPDF보다 훨씬 안정적이고 유지 보수가 잘됩니다.

    jre-headless가 필요합니다.

  13. from https://stackoverflow.com/questions/34837707/how-to-extract-text-from-a-pdf-file by cc-by-sa and MIT license