반응형
Opendart 공시서류원본파일 xml 파싱 방법
이 코드는 오픈DART(한국 금융감독원 전자공시 시스템) API를 사용하여 특정 문서(여기서는 감사보고서)를 ZIP 파일 형태로 다운로드하고, 해당 ZIP 파일 내에서 특정 XML 파일을 추출하여 HTML 구조로 파싱하는 과정을 구현. 이 과정에서 다양한 예외 처리를 통해 오류 상황을 세심하게 관리. 각 함수는 특정 작업을 수행하는 독립적인 단위로 구성되어 있어 코드의 가독성과 재사용성을 높임.
root를 통해서 xml 파일을 파싱하는 것을 성공함. 파이썬을 사용하여 이 과정을 처리했지만, 전통적인 방식과는 다른 접근으로 인해 약간의 어려움이 있었음. 먼저 XML 파일이 내부적으로 HTML 구조를 포함하고 있어 복잡한 형태로 되어 있었으며, 최신 공시된 파일의 경우, 파이썬의 최신 라이브러리를 통해 XML 파싱이 가능하지만, 옛날 파일은 전통적인 XML 구조가 아니어서 문제가 발생함.
인코딩 오류와 같은 문제로 HTML 구조로 파싱을 시도했으며, 약 20~30개 파일에 대해 테스트함. 이 과정은 전통적인 방식으로 어느 정도 성공했습니다. 테스트한 방법은 문제가 없었음. 적어도 xml 파싱을 위해서는 XML과 HTML을 모두 처리할 수 있는 파이썬 라이브러리(예: Beautiful Soup)의 선택이 중요했음. 그래서 'lxml' 라이브러리를 활용하여 최종적으로 전체 문서를 루트로 파싱하고, 각 요소를 성공적으로 처리할 수 있었음.
import requests
import zipfile
import io
from lxml import etree
import xml.etree.ElementTree as ET
def fetch_document(api_key, rcp_no):
# 오픈DART API에서 문서를 가져오기 위한 함수
url = 'https://opendart.fss.or.kr/api/document.xml'
params = {'crtfc_key': api_key, 'rcept_no': rcp_no} # API 키와 접수번호로 요청
response = requests.get(url, params=params)
if response.status_code != 200:
# 요청 실패 시 예외 발생
raise Exception(f"API 요청 실패: 상태 코드 {response.status_code}")
return response.content
def extract_audit_report(zip_content, rcp_no):
# ZIP 파일에서 감사보고서 XML 파일 추출
try:
with zipfile.ZipFile(io.BytesIO(zip_content)) as zf:
# 감사보고서 파일명 찾기
audit_fnames = [info.filename for info in zf.infolist() if f"{rcp_no}_00760.xml" in info.filename]
if not audit_fnames:
# 파일이 없는 경우 예외 발생
raise ValueError("감사보고서 파일을 찾을 수 없습니다.")
xml_data = zf.read(audit_fnames[0])
return xml_data
except zipfile.BadZipFile:
# ZIP 파일이 손상되었거나 유효하지 않은 경우 예외 발생
raise ValueError("ZIP 파일이 손상되었거나 유효하지 않습니다.")
def parse_html_from_xml(xml_data):
# XML 데이터에서 HTML 구조 파싱
try:
xml_text = xml_data.decode('euc-kr') # EUC-KR 인코딩 시도
except UnicodeDecodeError:
xml_text = xml_data.decode('utf-8') # 실패 시 UTF-8로 재시도
parser = etree.HTMLParser()
root = etree.fromstring(xml_text.encode('utf-8'), parser) # HTML 파싱
#pretty_html = etree.tostring(root, pretty_print=True, encoding='unicode')
#return pretty_html
return root
# 사용 예시
api_key = "api" #키값
rcp_no = "20140409001022" #공시번호
zip_content = fetch_document(api_key, rcp_no)
xml_data = extract_audit_report(zip_content, rcp_no)
root = parse_html_from_xml(xml_data) #성공!
반응형
댓글