[Python] office, pdf, eml 파일 불러오기

# LangChain 모듈 사용하는 방법

langchain에서 제공하는 document_loaders 를 이용하면 파일의 내용들을 손쉽게 파싱할 수 있다.

  • PDF: PyPDFLoader
  • eml: UnstructuredEmailLoader
  • xlsx: UnstructuredExcelLoader
  • docx: Docx2txtLoader
  • pptx: UnstructuredPowerPointLoader
from langchain_community.document_loaders import (
    PyPDFLoader, # .pdf
    UnstructuredEmailLoader, # .eml
    UnstructuredExcelLoader, # .xlsx, .xls
    Docx2txtLoader, # .docx
    UnstructuredPowerPointLoader, # .pptx
)
import htmltabletomd

def read_pdf(file_path:str)->str:
    '''
    Function which parses .pdf
    params:
      - file_path(str)
    returns:
      - (str)
    '''
    loader = PyPDFLoader(file_path)
    docs = loader.load()
    doc_content = ""
    for doc in docs:
        doc_content+= doc.page_content+"\n"

    return doc_content
    
    
def read_eml(file_path:str)->str:
    '''
    Function which parses .eml. This includes message only.
    params:
      - file_path(str)
    returns:
      - (str)
    '''
    loader = UnstructuredEmailLoader(file_path, mode="elements")
    docs = loader.load()
    doc_content = ''
    for doc in docs:
        if "message" in doc.metadata["filetype"]:
            doc_content+=doc.page_content+"\n"
    # doc = Document(page_content=doc_content, metadata=docs[0].metadata)
    return doc_content

def read_excel(file_path:str)->str:
    '''
    Function which parses .xlsx. This attaches sheet name as a header.
    params:
      - file_path(str)
    returns:
      - (str)
    '''
    loader = UnstructuredExcelLoader(file_path, mode="elements")
    docs = loader.load()
    doc_content=""
    for doc in docs:         
        doc_content="# 시트명: {}\n".format(doc.metadata["page_name"])    
        if "text_as_html" in doc.metadata:
            doc_content += htmltabletomd.convert_table(doc.metadata["text_as_html"])
        else:
            doc_content += doc.page_content.strip()

    return doc_content

def read_docx(file_path:str)->str:
    '''
    Function which parses .docx
    params:
      - file_path(str)
    returns:
      - (str)
    '''
    loader = Docx2txtLoader(file_path)
    docs = loader.load()
    doc_content = ""
    for doc in docs:
        doc_content+= doc.page_content+"\n"
    return doc_content

def read_pptx(file_path:str)->str:
    '''
    Function which parses .pptx
    params:
      - file_path(str)
    returns:
      - (str)
    '''
    loader = UnstructuredPowerPointLoader(file_path)
    docs = loader.load()
    doc_content = ""
    for doc in docs:
        doc_content+= doc.page_content+"\n"
    return doc_content

 

 

`htmltabletomd` 모듈은 이름 그대로 html의 표를 마크다운 표 형식으로 바꿔주는 모듈임

엑셀에서 텍스트만 파싱하면 탭과 줄바꿈으로만 파싱되어서 셀이 잘 구분이 안되길래 `mode="elements"` 옵션을 사용해서 html 형식으로 엑셀을 파싱한 후, 마크다운 형식으로 변환해줬다.

 

 

 

# MS Office 파일(.docx, .pptx, .xlsx) 불러오기

아래의 방법들은 Langchain 모듈 없이 다른 라이브러리로 읽는 방법이다.

  • python-docx: .docx 파일을 다룰 때 사용
  • openpyxl: .xlsx 파일을 다룰 때 사용
  • python-pptx: .pptx 파일을 다룰 때 사용
pip install python-docx openpyxl python-pptx

 

 

1) 워드 파일 읽기 (.docx)

# docx 파일 읽기

from docx import Document

def read_docx(file_path):
    doc = Document(file_path)
    full_text = []
    for para in doc.paragraphs:
        full_text.append(para.text)
    return '\n'.join(full_text)

# 사용 예시
file_path = 'your_doc_file.docx'
text = read_docx(file_path)
print(text)

 

 

2) ppt 파일 읽기 (.pptx)

from pptx import Presentation

def read_pptx(file_path:str)->str:
    loader = Presentation(file_path)
    doc_content = ""
    for slide in loader.slides:
      for shape in slide.shapes:
        if not shape.has_text_frame:
            continue
        for paragraph in shape.text_frame.paragraphs:
            for run in paragraph.runs:
              doc_content+= run.text+"\n"
        doc_content+="\n"
	return doc_content


# 사용 예시
file_path = 'your_file.pptx'
text = read_pptx(file_path)
print(text)

 

 

3) 엑셀 파일 읽기 (.xlsx)

from openpyxl import load_workbook

def read_xlsx(file_path):
    workbook = load_workbook(filename=file_path)
    sheet = workbook.active
    data = []
    for row in sheet.iter_rows(values_only=True):
        data.append(list(row))
    return data

# Example usage
xlsx_data = read_xlsx('sample.xlsx')
print(xlsx_data)

 

정형 데이터라 그런가 엑셀 읽는 라이브러리가  몇개 더 있는데 비교글을 보고 더 적합한 라이브러리를 고르면 될 듯

 

 

 

# pdf 파일 불러오기

잘 정리된 블로그를 발견했다.

 

Python으로 PDF에서 텍스트 추출하기(pdf to text)

파이썬으로 PDF파일에서 텍스트 추출하는 방법

wooiljeong.github.io

이것저것 비교해보고 싶었는데 결국 가장 많이 쓰이는 것으로 보이는 (구글 검색 기준) PyPDF2 를 사용하기로...

 

 

 

# eml 파일 불러오기

eml 파일은 메일에 대한 정보가 헤더로 들어있다. 헤더는 바이트로 디코딩을 해줘야함

기본 내장 라이브러리인 `email` 을 사용했다. 이 라이브러리는 `python>=3.5` 에서 부터 적용이 되는 듯...

 

import email
from email.header import decode_header
from bs4 import BeautifulSoup

def read_eml(file_path:str)->str:
    with open(file_path, "rb") as loader:
      docs = loader.read()
    docs = email.message_from_bytes(docs)
    
    decoded_bytes, charset = decode_header(docs.get('From'))[0]
    sender = decoded_bytes.decode(charset)
    decoded_bytes, charset = decode_header(docs.get('To'))[0]
    recipient = decoded_bytes.decode(charset)
    decoded_bytes, charset = decode_header(docs.get('Subject'))[0]
    subject = decoded_bytes.decode(charset)

    body = ""
    attachments = []

    for part in docs.walk():
      content_type = part.get_content_type()
      if content_type=='text/plain':
        body += part.get_payload(decode=True).decode('utf-8', 'ignore')
        
      elif content_type=='text/html':
        html_body = part.get_payload(decode=True).decode('utf-8', 'ignore')
        soup = BeautifulSoup(html_body, 'html.parser')
        body += soup.get_text(strip=True,separator="\n")
      
      elif content_type.startswith('application'):
        decoded_bytes, charset = decode_header(part.get_filename())[0]
        attachments.append(decoded_bytes.decode(charset))

    doc_content = "발신자:{}\t 수신자:{}\n제목: {}\n본문: {}\n첨부파일:{}".format(sender, recipient, subject, body, ', '.join(attachments))
    return doc_content



 # 사용 예시
file_path = 'your_file.eml'
text = read_eml(file_path)
print(text)

 

 

 

 

 

 

Reference

[1] Python으로 PDF에서 텍스트 추출하기(pdf to text)

[2] 파이썬에서 엑셀을 사용하는 3가지 방법

 

 

728x90