본문 바로가기

코딩

OPENDART API를 활용하여 파이썬으로 기업 정보 검색하기

사진: Unsplash 의 Towfiqu barbhuiya

전자공시시스템에는 기업의 현황, 재무정보, 지배구조 등 각 기업의 다양한 정보가 게시됩니다. 이런 공시정보는 시장조사 또는 투자의사결정 등을 위해 다양하게 활용되는데요, 오늘 포스트에서는 파이썬을 활용하여 기업별 매출액, 영업이익 등 공시 재무정보를 대량으로 조회하는 방법을 소개하겠습니다.

 

1. OPEN DART API 신청

파이썬을 통해 공시정보를 조회하기 위해서는 먼저 API 키가 필요합니다. 전자공시 OPENDART 시스템에 접속하여 API 키를 신청할 수 있습니다. API는 쉽게 설명하자면 정보 또는 명령을 주고받는 방법을 의미하고, API 키는 정보 또는 명령을 요청하기 위한 개인의 인증정보라고 표현할 수 있을 것 같습니다. 자동차에 시동을 걸기위해 키가 필요하듯 정보를 요청하기위해 필요한 키인 셈입니다.

 

OPENDART API 신청화면
발급된 API 확인

 

2. 개발가이드 확인하기

개발가이드 화면에서 API를 통해 ① 어떤 정보를  ② 어떻게 요청할 수 있는지 확인할 수 있습니다. 오늘의 예제인 매출액, 영업이익 조회를 위해서는 상장기업 재무정보 - 단일회사 주요계정 개발 가이드를 참고할 수 있습니다.

상장기업 재무정보 조회방법

위 화면을 보면 API 인증키, (기업의)고유번호, 사업연도, 보고서 코드가 있으면 원하는 정보를 요청할 수 있다는 것을 알 수 있는데요, 예시로 삼성전자(올라라 제발.. ㅠㅜ)의 2023년 상반기 재무실적을 조회해보겠습니다.

 

[매개변수]

  • 요청URL : https://opendart.fss.or.kr/api/fnlttSinglAcnt.json
    * 본 예제에서는 JSON 포맷으로 데이터를 요청하겠습니다
  • API 인증키 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    * 개인별로 발급된 API키를 활용
  • 고유번호 : 00126380 (삼성전자)
    * 첨부된 기업별 고유번호 엑셀파일을 참고
  • 사업연도 : 2023
  • 보고서 코드 : 11012 (반기보고서)

기업별 고유번호_230819.xlsx
3.63MB

 

[최종 요청 URL]

https://opendart.fss.or.kr/api/fnlttSinglAcnt.json?crtfc_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&corp_code=00126380&bsns_year=2023&reprt_code=11012

 

개인 인증키를 XXXX로 표현했는데요, 본인의 API키를 해당 자리에 넣어서 위 최종 요청 URL을 웹브라우저 주소창에 입력해보면 다음과 같은 결과를 얻을 수 있습니다.

API 회신값 (삼성전자, '23년 2분기 실적)

개발가이드를 통해 API를 통한 요청을 어떻게 보내야 하는지를 확인해보았는데요. 다음 스텝으로는 위 과정을 파이썬으로 어떻게 수행할 수 있는지 알아보겠습니다.

 

3. 파이썬으로 API 요청 주고 받기

import requests
# 정보 요청을 위한 함수 정의
def get_dart_data(url, params):
    return requests.get(url, params=params)
# 요청을 위한 매개변수 (parameters)는 dictionary 형식으로 입력합니다.

정보 요청을 위해서 requests 라이브러리를 활용합니다. 설치되어있지 않다면 pip install requests 로 설치할 수 있습니다.

 

위의 삼성전자의 예시를 파이썬코드로 작성해보면 아래와 같습니다.

data_samsung = get_dart_data('https://opendart.fss.or.kr/api/fnlttSinglAcnt.json', 
                              params = {'crtfc_key':apikey,
                                        'corp_code':'00126380',
                                        'bsns_year':'2023',
                                        'reprt_code':'11012'}
                              )
data_samsung = data_samsung.json()

반환된 data는 status, message, list값을 가집니다. 정보가 정상적으로 조회되었다면 stasut는 '000', message는 '정상'값을 가집니다. list에는 조회된 정보가 dictionary형태로 담겨있는데요, 익숙한 pandas DataFrame형태로 변환해보면 다음과 같습니다.

import pandas as pd
df_samsung = pd.DataFrame(data_samsung['list'])

df_samsung

다음으로는 모든 상장기업에 대한 정보를 조회하여 하나의 엑셀파일로 저장해보겠습니다.


[전체 기업 리스트 읽어오기]

corps = pd.read_excel("기업별 고유번호_230819.xlsx", dtype={'corp_code':str,'stock_code':str})
# 기업 고유번호가 0으로 시작하는 경우 int로 읽어오면 앞자리 0이 사라지기 때문에
# dtype(데이터 타입)을 str로 지정해줍니다.

corps = corps[corps['stock_code'].notna()].copy()
# stock_code가 빈값이 아닌 (상장되어 주식의 종목코드가 있는) 회사들만 남깁니다.

 

[각 기업별로 재무정보 조회하여 하나의 DataFrame으로 합치기]

from tqdm import tqdm #진행경과 확인용

# 비어있는 df 생성
financial_info = pd.DataFrame(columns = ['corp_code'])

for i, r in tqdm(corps.iterrows(), total = len(corps)):
    # financial_info에 조회하려는 회사가 없을 때만 조회 실행
    if r['corp_code'] not in financial_info['corp_code'].to_list():
        data = get_dart_data('https://opendart.fss.or.kr/api/fnlttSinglAcnt.json', 
                              params = {'crtfc_key':apikey,
                                        'corp_code':r['corp_code'],
                                        'bsns_year':'2023',
                                        'reprt_code':'11012'}
                              )
        data = data.json()
        # 정상적으로 정보가 조회된 경우 조회된값을 financial_info에 합치기
        if data['status'] == '000':
            returned_df = pd.DataFrame(data['list'])
            financial_info = pd.concat([financial_info, returned_df], sort=False)

조회된 financial_info를 엑셀로 저장해보면 다음과 같습니다.

상장기업 재무정보_23.2Q_230819.xlsx
5.54MB

 

상장기업 리스트에 매출, 영업이익 정보를 붙여보겠습니다.

import itertools
for x in itertools.product(['연결재무제표','재무제표'], ['매출액','영업이익']):
    query = financial_info.query(f"(fs_nm == '{x[0]}') and (account_nm == '{x[1]}')")
    column_name = (lambda x: f'{x[1]}(연결)' if x[0].startswith('연결') else x[1])(x)
    query = query.rename({'thstrm_amount':column_name}, axis='columns').copy()
    corps = corps.merge(query[['corp_code', column_name]], on='corp_code', how='left')

결과를 엑셀로 다운받아보면 다음과 같습니다.

상장기업별 매출액 및 영업이익_23.2Q_230819.xlsx
0.27MB
재무정보 조회 결과 (23.2Q 상장기업 매출액 및 영업이익)

한가지 아쉬운점은 DART에서는 각 기업들이 입력한 정보를 그대로 제공하기 때문에 입력 값에 오류가 있는 경우도 보정없이 그대로 출력된다는 것입니다. 위 표를 보면 SG세계물산이 경단위의 매출을 기록한 것으로 나오는데 이렇게 터무니없는 값이 출력될 때도 있고, 표준 입력 양식을 지키지 않아 개별로 사업보고서를 검색하면 숫자가 보이는데 API로는 값이 출력되지 않는 경우도 있습니다. 이점 참고하시어 오늘 소개드린 튜토리얼을 활용하시면 좋을 것 같습니다.

 

오늘은 전자공시시시스템에서 제공하는 OPENDART API를 활용하는 방법을 알아보았습니다. DART뿐만 아니더라도 API서비스를 제공하는 시스템이 있다면 오늘 포스트를 참고하여 활용하실 수 있을 것 같습니다. 향후 추가로 다루었으면 하는 주제가 있으시면 댓글로 알려주세요!

 

감사합니다.