반응형

안녕하세요, 왕초보 코린이를 위한 코딩유치원에 오신 것을 환영합니다.

코딩유치원에서는 파이썬 기초부터 사무자동화, 웹크롤링, 데이터 분석 등의 다양한 패키지까지 초보자도 알기 쉽도록 내용을 정리해 놓았습니다.

업무는 물론 투자에도 도움이 될만한 전자공시시스템(DART) 텔레그램(Telegram) 관련 패키지도 배울 수 있으니 많은 관심 부탁드립니다.

 

 

오늘은 어느 독자분의 질문에 답해드리기 위해서 글을 써보려 합니다.

 

질문의 핵심은 다음과 같았습니다.

 

파이썬으로 PDF 파일을 읽어서 검색으로 특정 문자를 찾고 그 문제에 대해 형광펜으로 강조하고 싶은데, 어떻게 해야할지 몰라 문의드립니다.

 

자 그럼 이 문제를 해결하기 위해서 함께 방법을 알아보겠습니다.

 

 


1. PyMuPDF란?

 

PyMuPDF는 Python용 PDF 처리 라이브러리로, PDF 파일의 생성, 수정, 추출, 텍스트 검색, 이미지 추출 등 다양한 작업을 수행할 수 있습니다. 챗GPT에게 물어보니 제가 항상 사용하던 PyPDF2 보다 더  빠른 속도와 더 많은 기능을 제공하며, 특히 큰 규모의 PDF 파일에 대해서도 효율적으로 작동하는 패키지라고 하네요.

 

패키지 설치는 터미널에 아래의 코드를 입력 후 엔터를 눌러주시면 진행 됩니다.

pip install pymupdf

 

아래와 같은 메시지가 출력되면 설치가 정상적으로 완료된거예요. 

 

2. 형광펜으로 특정 문자 강조하기

 

새롭게 알게 된 PyMuPDF의 전체적인 기능에 대해서는 차차 알아가는 걸로 하고, 오늘은 바로 독자분의 궁금증을 해결해보도록 하겠습니다. 전체적인 코드는 아래와 같습니다.

 

주석을 자세하게 달아 두었으니 코드의 흐름만 간단히 써보겠습니다.

 

1) PyMuPDF 패키지 import (불러올 때는 fitz라는 이름으로 불러옴에 주의!)

2) 불러올 pdf 경로, 저장할 경로, 검색할 텍스트 변수에 입력

3) 앞서 정의한 함수(higlight_text_in_pdf)에 인자 입력하여 함수 실행

4) 함수 내부 동작

    - 강조하고 싶은 PDF 불러오기

    - 전체 페이지 각각 가져오면서 텍스트 검색

    - 검색 텍스트와 일치된 텍스트 강조 (색상은 R, G, B 순이며 1,1,0은 노란색, 0,1,0은 초록색)

    - 저장 후 닫기

 

# PyMuPDF 패키지 불러오기
import fitz  

# 함수 정의
def highlight_text_in_pdf(input_pdf_path, output_pdf_path, search_text):

    # PDF 파일 열기
    pdf_document = fitz.open(input_pdf_path)

    # PDF의 각 페이지를 순회하며
    for page_number in range(len(pdf_document)):
        # 페이지 가져오기
        page = pdf_document.load_page(page_number)

        # 페이지에서 텍스트 검색
        matches = page.search_for(search_text)

        # 각 일치 항목을 강조
        for match in matches:
            # 일치 항목의 사각형 좌표 가져오기
            highlight = page.add_highlight_annot(match)

            # 강조의 색상 설정 (예: 노란색)
            highlight.set_colors({"stroke": (1, 1, 0), "fill": (1, 1, 0)})

    # 수정된 PDF 저장
    pdf_document.save(output_pdf_path)
    pdf_document.close()

# 사용 예시
input_pdf_path = "input.pdf"  # 입력 PDF 파일 경로
output_pdf_path = "output.pdf"  # 출력 PDF 파일 경로
search_text = "검색할_텍스트"  # 검색하고자 하는 텍스트

# 함수 실행
highlight_text_in_pdf(input_pdf_path, output_pdf_path, search_text)

 

[실행 결과] _ 보유하고 있던 PDF 문서에서 '빅데이터'만 노란색 형광펜 표시

 


 

오늘 준비한 내용은 여기까지 입니다. 오늘 배운 PyMuPDF를 이용해 텍스트나 이미지도 추출 가능하다고 하니 빨리 공부해서 포스팅 해보도록 하겠습니다.

 

감사합니다.

반응형
반응형

안녕하세요, 왕초보 코린이를 위한 코딩유치원에 오신 것을 환영합니다.

코딩유치원에서는 파이썬 기초부터 사무자동화, 웹크롤링, 데이터 분석 등의 다양한 패키지까지 초보자도 알기 쉽도록 내용을 정리해 놓았습니다.

업무는 물론 투자에도 도움이 될만한 전자공시시스템(DART) 텔레그램(Telegram) 관련 패키지도 배울 수 있으니 많은 관심 부탁드립니다.

 

 

오늘은 파이썬으로 pdf 파일을 다루는 법에 대해서 공부해보겠습니다.

 

<목차>

1. PyPDF2란?

2. 페이지 추출

3. PDF 분할

4. PDF 회전

5. PDF 병합

 


1. PyPDF2란?

 

PyPDF2는 이름에서 직관적으로 알 수 있듯이 Python으로 PDF 문서를 다룰 수 있게 해주는 라이브러리입니다.

 

참고로 설치는 아래의 코드 한 줄을 커맨드 창에 입력해주시면 됩니다. 대소문자에 주의해주세요!

 

pip install PyPDF2

 

아래의 링크는 PyPDF2 공식 문서이며, 그 안에는 여러 기능들이 있지만 이번 시간에는 코딩유치원 컨셉에 맞게 최대한 쉽고 가장 자주 사용할 만한 기능 위주로 설명드리겠습니다.

 

https://pythonhosted.org/PyPDF2/

 

PyPDF2 Documentation — PyPDF2 1.26.0 documentation

 

pythonhosted.org

 

 

PyPDF2는 크게 3가지 클래스)로 나눌 수 있습니다.

 

 

1) 원하는 작업을 하기 위해 pdf 파일을 불러올 때 사용하는 PdfFileReader

 

2) 회전, 추출, 분리 등의 페이지 단위 작업을 할 때 사용하는 PdfFileWriter

     (참고로, 회전은 한번에 하는 것이 아니라, 페이지 하나씩 돌려서 새로운 pdf에 붙여넣는 방식입니다)

 

3) 여러 pdf 파일을 하나의 pdf로 병합할 때 사용하는 PdfFileMerger

 

 

<2023.02.11 - PyPDF2 버전 3.0.1 기준 변경 사항>

 

PdfFileReader → PdfReader

PdfFileWriter → PdfWriter

PdfFileMerger → PdfMerger

지금부터는 위에서 배운 PyPDF2 모듈들을 이용해서 우리가 자주 사용하는 기능들을 구현해보겠습니다.

 


 

2. 페이지 추출

 

가장 처음으로 원하는 페이지를 추출해보겠습니다.

 

저는 쉬운 이해를 위해서 테스트용 PDF를 만들어서 사용하였으나, 여러분들은 각자의 PDF 파일을 사용하시면 되는 점 참고바랍니다.

 

테스트 PDF 파일 1.pdf에서 2번째 페이지만 추출해서 따로 저장해보겠습니다.

 

<코드>

# step1.관련 모듈 import
from PyPDF2 import PdfFileReader, PdfFileWriter

# step2.기존 pdf 불러오기
pdfReader = PdfFileReader("테스트 PDF 파일 1.pdf", "rb")

# step3.새로 만들 pdf 객체 생성
pdfWriter = PdfFileWriter()

# step4.기존의 1번 페이지를 가져와서 새로만든 pdf에 붙여넣기
pdfWriter.addPage(pdfReader.getPage(1))

# step5.1번 페이지가 붙여진 새로운 pdf 파일을 현재 경로('./')에 원하는 이름으로 저장
pdfWriter.write(open("./추출한 테스트 PDF 파일.pdf", "wb"))

 

<코드> PyPDF2 (ver 3.0.0 이상)

 

* 변경점

addPage(page_number) → add_page(page_number)

.getPage(page_number) → .pages[page_number] 

# step1.관련 모듈 import
from PyPDF2 import PdfReader, PdfWriter

# step2.기존 pdf 불러오기
pdfReader = PdfReader("테스트 PDF 파일 1.pdf", "rb")

# step3.새로 만들 pdf 객체 생성
pdfWriter = PdfWriter()

# step4.기존의 1번 페이지를 가져와서 새로만든 pdf에 붙여넣기
pdfWriter.add_page(pdfReader.pages[1])

# step5.1번 페이지가 붙여진 새로운 pdf 파일을 현재 경로('./')에 원하는 이름으로 저장
pdfWriter.write(open("./추출한 테스트 PDF 파일.pdf", "wb"))

 

<결과물>

 


 

3. PDF 분할

 

다음으로 구현해 볼 기능은 페이지를 회전하는 것입니다.

 

거의 비슷하지만 2가지가 다릅니다.

 

1) 기존 PDF의 페이지 수를 파악해서 for문으로 한 페이지씩 처리

 

    - numPages 함수로 기존 PDF 파일의 전체 페이지 수 파악

    - getPage( ) 함수로 지정한 PDF 페이지 한 장 가져오기

 

2) 마지막 저장 시, f 문자열 포매팅 개념을 이용해서 pageNum 변수를 파일명에 반영

 

 

<코드>

# step1.관련 모듈 import
from PyPDF2 import PdfFileReader, PdfFileWriter

# step2.기존 PDF 불러오기
pdfReader = PdfFileReader("테스트 PDF 파일 1.pdf", "rb")

# 페이지 하나씩 받아와서 저장하는 반복문
for pageNum in range(pdfReader.numPages):
    
    # step3.새로 만들 pdf 객체 생성 (계속 누적되지 않기 위해 for문 안으로 넣음)
    pdfWriter = PdfFileWriter()
    
    # step4.기존 PDF에서 한 페이지씩 가져오기
    page = pdfReader.getPage(pageNum)
    
    # step5.위에서 가져온 페이지를 새로 만든 PDF에 붙여넣기
    pdfWriter.addPage(page)

    # step6.새로운 PDF 파일을 해당 경로('./')에 원하는 이름으로 저장
    # (이름을 계속 다르게 해주기 위해서 f 문자열 포매팅 개념을 이용)
    pdfWriter.write(open(f"./분할한 PDF 파일 {pageNum+1}.pdf", "wb"))

 

<코드> PyPDF2 (ver 3.0.0 이상)

 

* 변경점

pdfReader.numPages → len(pdfReader.pages)

addPage(page_number) → add_page(page_number)

.getPage(page_number) → .pages[page_number] 

 

# step1.관련 모듈 import
from PyPDF2 import PdfReader, PdfWriter

# step2.기존 PDF 불러오기
pdfReader = PdfReader("테스트 PDF 파일 1.pdf", "rb")


# 페이지 하나씩 받아와서 저장하는 반복문
for pageNum in range(len(pdfReader.pages)):
    
    # step3.새로 만들 pdf 객체 생성 (계속 누적되지 않기 위해 for문 안으로 넣음)
    pdfWriter = PdfWriter()
    
    # step4.기존 PDF에서 한 페이지씩 가져오기
    page = pdfReader.pages[pageNum]
    
    # step5.위에서 가져온 페이지를 새로 만든 PDF에 붙여넣기
    pdfWriter.add_page(page)

    # step6.새로운 PDF 파일을 해당 경로('./')에 원하는 이름으로 저장
    # (이름을 계속 다르게 해주기 위해서 f 문자열 포매팅 개념을 이용)
    pdfWriter.write(open(f"./분할한 PDF 파일 {pageNum+1}.pdf", "wb"))

 

<결과물>


 

4. PDF 회전

 

위에서 배운 PDF 분할에서 딱 2가지만 달라졌습니다.

 

1) rotate( ) 함수로 회전

 

2) pdfWriter가 for문 밖으로 나감 (기존의 pdf를 회전시키고 새로운 PDF에 계속 붙여넣어 주어야하기 때문)

 

이 부분에 유의하시면서 아래의 코드를 보시면 좋을 것 같습니다.

 

# step1.관련 모듈 import
from PyPDF2 import PdfFileReader,PdfFileWriter

# step2.기존 pdf 불러오기
pdfReader = PdfFileReader(open("테스트 PDF 파일 1.pdf","rb"))

# step3.새로 만들 pdf 객체 생성
pdfWriter = PdfFileWriter()

# 페이지 하나씩 받아와서 돌린 후, 붙여넣는 반복문
for pageNum in range(pdfReader.numPages):

	# step4.기존 PDF에서 한 페이지씩 가져오기
    page = pdfReader.getPage(pageNum)
    
    # step5.시계 방향으로 90도 회전 (반시계로 90도 회전은 270 입력하면 됨)
    page.rotateClockwise(90)
    
    # step6.회전된 페이지 새로운 PDF에 붙여넣기
    pdfWriter.addPage(page)

# step7.새로운 pdf 파일을 해당 경로('./')에 원하는 이름으로 저장
pdfWriter.write(open('./회전한 테스트 PDF 파일.pdf', 'wb'))

 

<코드> PyPDF2 (ver 3.0.0 이상)

 

* 변경점

rotateClockwise( ) → rotate( )

pdfReader.numPages → len(pdfReader.pages)

addPage(page_number) → add_page(page_number)

.getPage(page_number) → .pages[page_number] 

 

# step1.관련 모듈 import
from PyPDF2 import PdfReader, PdfWriter

# step2.기존 pdf 불러오기
pdfReader = PdfReader("데이터 자격시험 일정_2022.pdf", "rb")

# step3.새로 만들 pdf 객체 생성
pdfWriter = PdfWriter()

# 페이지 하나씩 받아와서 돌린 후, 붙여넣는 반복문
for pageNum in range(len(pdfReader.pages)):

	# step4.기존 PDF에서 한 페이지씩 가져오기
    page = pdfReader.pages[pageNum]
    
    # step5.시계 방향으로 90도 회전 (반시계로 90도 회전은 270 입력하면 됨)
    page.rotate(90)
    
    # step6.회전된 페이지 새로운 PDF에 붙여넣기
    pdfWriter.add_page(page)

# step7.새로운 pdf 파일을 해당 경로('./')에 원하는 이름으로 저장
pdfWriter.write(open('./회전한 테스트 PDF 파일.pdf', 'wb'))

 

<결과물>

 


 

4. PDF 병합

 

병합은 앞서 배운 분할과 회전에 비해서 매우 간단합니다.

 

PdfFileWriter가 아니라 PdfFileMerger를 import 해준 점만 주의 하시면 아래 코드 이해하시는데에 어려움 없으시리라 생각합니다.

 

 

<코드>

# step1.관련 모듈 import (Writer 대신 Merger를 사용하는 것에 주의!)
from PyPDF2 import PdfFileReader, PdfFileMerger

# step2.기존 pdf 불러오기
pdfReader1 = PdfFileReader(open("테스트 PDF 파일 1.pdf","rb")) # 3장
pdfReader2 = PdfFileReader(open("테스트 PDF 파일 2.pdf","rb")) # 2장

# step3.새로 만들 pdf 객체 생성 (병합용)
pdfMerger = PdfFileMerger()

# step4.PDF 하나씩 가져와서 차례대로 병합
pdfMerger.append(pdfReader1)
pdfMerger.append(pdfReader2)

# step5.새로운 pdf 파일을 해당 경로('./')에 원하는 이름으로 저장
pdfMerger.write("./병합한 테스트 PDF 파일.pdf")

 

<코드> PyPDF2 (ver 3.0.0 이상)

 

* 변경점

PdfReader와 PdfMerger 클래스 외에는 따로 변경점 없음

# step1.관련 모듈 import (Writer 대신 Merger를 사용하는 것에 주의!)
from PyPDF2 import PdfReader, PdfMerger

# step2.기존 pdf 불러오기
pdfReader1 = PdfReader(open("분할한 PDF 파일 1.pdf","rb")) # 3장
pdfReader2 = PdfReader(open("분할한 PDF 파일 2.pdf","rb")) # 2장

# step3.새로 만들 pdf 객체 생성 (병합용)
pdfMerger = PdfMerger()

# step4.PDF 하나씩 가져와서 차례대로 병합
pdfMerger.append(pdfReader1)
pdfMerger.append(pdfReader2)

# step5.새로운 pdf 파일을 해당 경로('./')에 원하는 이름으로 저장
pdfMerger.write("./병합한 테스트 PDF 파일.pdf")

 

<결과물>

 


오늘 준비한 내용은 여기까지입니다.

 

관련 내용을 한 번에 다 넣으려다 보니 글이 길어졌네요.

 

다음에 시간을 내어서 Tkinter와 연동해서 간단하게 GUI 기반의 PDF 변환 프로그램을 만들어 보겠습니다.

 

오늘도 공부하시느라 고생 많으셨습니다~

반응형

+ Recent posts