본문 바로가기

~2023

[DART] 공시대상회사 정보 가져오기

728x90
반응형

대한민국 전자공시시스템(DART : Data Analysis, Retrieval and Transfer System)은 상장법인 등이 공시서류를 인터넷으로 제출하고, 투자자 등 이용자는 제출 즉시 인터넷을 통해 조회할 수 있도록 하는 종합적 기업공시 시스템이다.
웹 사이트에 접속해 검색이 가능하지만 좀 더 방대한 자료를 원한다면 DART에서 API를 제공하기 때문에 python 코드로 손쉽게 구현 가능하다. Open API Key는 여기에서 받으면 되고, 일일 호출 2만 회로 제한되어 있다.

다양한 API를 제공하기 때문에 원하는 정보를 손쉽게 가져올 수 있지만, 우선적으로 작업해야 하는 것이 있다. 그건 기업 정보를 가지고 있어야 해당 기업 검색이 가능한데 [개발 가이드] > [공시 정보] > [4. 고유번호]를 자세히 보면 DART에 등록되어있는 공시대상회사의 고유번호,회사명,종목코드, 최근변경일자를 파일로 제공한다. 그래서 오늘은 기업 정보를 가져오는 방법을 공유하겠다.

1. 필요한 라이브러리 import

import ssl, os
import xml.etree.ElementTree as et
import pandas as pd

from urllib import request
from zipfile import ZipFile

url를 통해 정보를 가져올 것이기 때문에 request가 필요하고 도메인이 https이기 때문에 ssl를 같이 사용한다. 그리고 데이터를 zip 파일을 다운 받기 때문에 압축 해제를 위해 zipfile을 사용하고 압축 해제하면 xml 파일이 나오기 때문에 xml을 컨트롤해 csv 파일로 만들기 위해 xml와 pandas를 사용한다.

2. API 호출해 파일 다운로드

# OPEN API Key 가져오기
with open('data/key.txt', 'r') as f:
    API_KEY = f.readline()

context = ssl._create_unverified_context() # https 호출을 위한 ssl

'''공시 정보가 담긴 파일 가져오기'''
url = "https://opendart.fss.or.kr/api/corpCode.xml?crtfc_key=" + API_KEY
data = request.urlopen(url, context=context)
filename = data.info().get_filename()

# zip 파일 다운로드
with open(f"./data/{filename}", 'wb') as f:
    f.write(data.read())

# 현재 디렉토리에 압축 해제 -> xml 파일 생성
with ZipFile(f"./data/{filename}", 'r') as zipObj:
    zipObj.extractall('./data/')

# 원본 압축 파일 삭제
if os.path.isfile(f"./data/{filename}"):
    os.remove(f"./data/{filename}")

API_KEY 값을 그대로 복사+붙여넣기 해도 되지만, 나는 Github에서 관리하고 있기 때문에 Private하게 관리하기 위해 별도 파일 안에 API KEY 정보를 넣고 읽어서 활용하는 방법을 선택했다.
그리고 https에 요청하는 경우 connection 에러가 뜰 때도 있다고 해서 ssl._create_unverified_context()를 사용했다. 그렇게 [4. 고유번호] 안내에 따라 url를 설정하고 자료를 요청하면 data에 원하는 정보가 담겨 있다.
그래서 data를 zip 파일로 다운 받고 해제하여 xml 파일을 만든 후에 원본 zip 파일은 삭제해줬다.

3. 상장된 기업 정보만 추출해 csv 파일화

'''상장된(종목코드가 있는) 기업만 추출'''
tree = et.ElementTree(file=f"./data/{filename.split('.')[0]}.xml")
columns = ['corp_code', 'corp_name', 'stock_code', 'modify_date']
DB = {key: [] for key in columns}

# xml 파일 데이터 읽기
for row in tree.getroot().findall('list'):
    for column in columns:
        DB[column].append(row.find(column).text)

# DataFrame으로 만들기
company_df = pd.DataFrame()
for column in columns:
    company_df[column] = list(map(str, DB[column]))

# stock_code가 빈 데이터는 제거
stock_corp = company_df[company_df['stock_code'] != ' ']
stock_corp.to_csv(f"{filename}.csv", index=False)

xml 파일을 읽어 tree에 저장하고 DataFrame에 열로 데이터를 추가하기 위한 DB도 선언해준다.
xml 파일은 다음과 같이 선언되어 있다.

<result>
    <list>
        <corp_code>00434003</corp_code>
        <corp_name>다코</corp_name>
        <stock_code> </stock_code>
        <modify_date>20170630</modify_date>
    </list>
    ...
</result>

corp_code는 기업 고유 번호, corp_name은 정식명칭, stock_code는 종목코드로 비상장 기업이면 ' '으로 되어 있으며 modify_date는 최종변경일자를 뜻한다.
그래서 tree의 getroot()인 <result>에서 모든 list를 호출해 DB에 순서대로 값이 쌓이도록 했다.
그런 다음에 모든 기업 정보가 담긴 DB로 DataFrame을 만들고 우리는 상장된 기업 정보만 필요하기 때문에 stock_code가 ' '인 것을 제외하고 return 받아 csv 파일로 저장하면 끝이다.

728x90
반응형