Skip to content

dart

2 posts with the tag “dart”

파이썬으로 DART에서 재무제표 수집하기

이번 포스트에서는 전자공시시스템(DART)에서 제공하는 재무제표를 파이썬으로 다운로드하고 파싱하는 방법을 다룹니다.

DART에서 재무제표를 얻어오는 방법은 다양한데 여기서는 두 가지 방법을 다룹니다.

첫 번째로 단일회사 주요계정 API를 활용한 방법입니다.

DART Open API를 사용하려면 인증키가 필요합니다. 인증키 획득 방법은 이 포스트에서 확인하세요.

다음은 단일회사 주요계정 API를 호출하여 재무제표 정보를 획득하는 함수 입니다. 인증키, 회사 고유번호, 사업연도, 보고서 코드를 입력하여 재무제표를 받아올 수 있습니다.

def get_fs(crtfc_key, corp_code, bsns_year, reprt_code):
# 단일회사 주요계정
# crtfc_key API 인증키 STRING(40) Y 발급받은 인증키(40자리)
# corp_code 고유번호 STRING(8) Y 공시대상회사의 고유번호(8자리)
# ※ 개발가이드 > 공시정보 > 고유번호 API조회 가능
# bsns_year 사업연도 STRING(1) Y 사업연도(4자리)
# ※ 2015년 이후 부터 정보제공
# reprt_code 보고서 코드 STRING(5) Y 1분기보고서 : 11013
# 반기보고서 : 11012
# 3분기보고서 : 11014
# 사업보고서 : 11011
api = 'https://opendart.fss.or.kr/api/fnlttSinglAcnt.json'
params = {
'crtfc_key': crtfc_key,
'corp_code': corp_code,
'bsns_year': bsns_year,
}
data = []
reprt_name = REPRT_NAMES.get(reprt_code, "")
params['reprt_code'] = reprt_code
res = self._request(api, params=params)
if res is None:
return None
if res.status_code != 200:
return None
item = json.loads(res.text)
if item.get('status', '') != '000':
return None
for _item in item.get('list'):
_item['corp_code'] = corp_code
_item['reprt_code'] = reprt_code
_item['reprt_name'] = reprt_name
data.append(_item)
return data

get_fs(crtfc_key, '00266961', 2015, '11011')와 같이 호출하면 다음과 같은 결과를 받아올 수 있습니다.

[{'account_nm': '자산총계', 'bfefrmtrm_amount': '9,881,190,909,324', 'bfefrmtrm_dt': '2018.12.31 현재', 'bfefrmtrm_nm': '제 20 기', 'bsns_year': '2020', 'corp_code': '00266961', 'frmtrm_amount': '12,299,527,120,786', 'frmtrm_dt': '2019.12.31 현재', 'frmtrm_nm': '제 21 기', ...}, {'account_nm': '부채총계', 'bfefrmtrm_amount': '3,932,050,396,031', 'bfefrmtrm_dt': '2018.12.31 현재', 'bfefrmtrm_nm': '제 20 기', 'bsns_year': '2020', 'corp_code': '00266961', 'frmtrm_amount': '5,795,601,052,206', 'frmtrm_dt': '2019.12.31 현재', 'frmtrm_nm': '제 21 기', ...}, ...]

DART Open API 재무정보 일괄 다운로드

Section titled “DART Open API 재무정보 일괄 다운로드”

두 번째는 재무정보 일괄 다운로드로 한꺼번에 전체 기업의 재무제표 데이터를 받아오는 방법입니다. Open DART 사이트에서 공시정보 활용마당 / 재무정보 일괄다운로드를 클릭하면 다음과 같은 테이블을 볼 수 있습니다.

재무정보 일괄다운로드

여기서 다운로드 하면 해당 연도와 분기의 네 종류의 재무제표를 압축파일로 다운 받을 수 있습니다. 여기서는 다운로드, 압축해제를 포함하여 파이썬에서 재무제표를 읽어오는 방법을 다룹니다.

다음은 Selenium으로 다운로드 버튼을 클릭하여 파일을 다운로드하고 압축을 해제하는 코드입니다.

options = webdriver.ChromeOptions()
options.add_experimental_option("prefs", {
"download.default_directory": self.job_base,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
})
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
browser = webdriver.Chrome(executable_path=os.path.join(settings.QUANTYLAB_BASE, 'drivers/chromedriver'), chrome_options=options)
try:
browser.get('https://opendart.fss.or.kr/disclosureinfo/fnltt/dwld/main.do')
elem = browser.find_element_by_css_selector('table.tb01')
for elem_a in elem.find_elements_by_link_text('다운로드'):
filename = re.findall(r'.*\(.*\'(.+)\'\).*', elem_a.get_attribute('onclick'))[0]
# 파일 다운로드
elem_a.click()
time.sleep(10)
# 압축파일 로드
filepath = os.path.join(base, filename)
z = zipfile.ZipFile(filepath)
for info in z.infolist():
# 한글 파일명 인코딩 수정
_filename = info.filename.encode('cp437').decode('euc-kr')
_filepath = os.path.join(base, _filename)
if os.path.exists(_filepath):
continue
info.filename = _filename
# 압축해제
z.extract(info, base)
z.close()
except Exception as e:
print(str(e))
finally:
browser.quit()

이렇게 압축해제까지 하면 2020_1분기보고서_04_현금흐름표_20210211.txt과 같은 파일들이 생성되어 있을 것입니다.

이 텍스트 파일은 다음과 같이 pandas로 쉽게 DataFrame으로 읽어올 수 있습니다. 다만 sepencoding을 다음과 같이 적절하게 정해주는 것이 중요합니다.

df = pd.read_csv(filepath, sep='\t', encoding='cp949')

여기서 당기, 당기 1분기, 당기 반기 등의 다양한 컬럼이 생기는데 저는 이들을 당기로 통합하여 정리했습니다.

다음은 포괄손익계산서의 일부 항목을 나타낸 것입니다.

항목명결산기준일보고서종류당기
영업수익2018-12-31사업보고서5,586,904,533,355
영업이익(손실)2018-12-31사업보고서942,532,561,543
당기순이익(손실)2018-12-31사업보고서627,901,873,332

그런데 재무제표를 볼 때 항목의 흐름을 보는 것이 중요합니다. 예를 들어 영업 이익이 꾸준히 증가하고 있는지를 보고 싶은 것입니다.

그래서 동일 항목에 대해서 결산기준일 순서대로 DataFrame을 재구성하고자 합니다. 이를 위해 DataFramepivot 함수를 사용합니다.

df_pivot = df.pivot(values='value', index='항목명', columns='결산기준일')

동일 항목이지만 항목명이 다르게 적혀있는 경우가 있어서 이를 맞춰주는 처리를 했습니다.

그럼 다음과 같이 동일 항목의 값을 분기 순서대로 볼 수 있습니다.

항목명2015-12-312016-03-312016-06-302016-09-302016-12-312017-03-312017-06-302017-09-302017-12-312018-03-312018-06-302018-09-302018-12-312019-03-312019-06-302019-09-302019-12-312020-03-312020-06-302020-09-30
매출액3,251,157,100,000937,280,220,152987,281,364,2951,013,075,223,7704,022,629,619,9821,082,247,281,1961,129,631,366,8471,200,676,275,2204,678,468,928,0321,309,059,864,2481,363,615,953,3321,397,713,834,6745,586,904,533,3551,510,861,770,2821,630,275,004,3951,664,815,000,0786,593,400,065,2441,732,064,462,0971,902,467,957,4911,360,779,374,259
영업이익762,203,849,000256,827,536,675272,663,961,847282,298,051,5251,102,040,475,792290,797,289,304285,213,522,180312,084,238,4441,179,187,806,331256,980,563,870250,583,189,279221,718,402,565942,532,561,543206,244,504,954128,334,709,480202,086,039,366710,070,173,513221,495,078,328230,597,573,115291,726,798,004
당기순이익516,986,279,000165,036,146,535213,223,506,226198,000,157,034759,072,951,187210,876,050,870171,420,229,303215,798,264,368770,101,670,207153,751,654,038281,758,577,70168,386,763,908627,901,873,33287,585,903,29027,756,852,97585,268,053,088396,821,062,465134,874,581,86590,682,203,810235,342,965,699

파이썬으로 DART OpenAPI 사용하기

이번 포스트에서는 금융감독원에서 운영하는 전자공시시스템(DART)의 OpenAPI를 사용하는 방법을 다룹니다. DART OpenAPI를 통해 기업의 재무제표 등 주식 투자에 도움이 되는 다양한 정보를 얻을 수 있습니다.

우선 DART 사이트 http://dart.fss.or.kr/에 접속합니다. 그리고 상단의 작은 메뉴에서 오픈API 메뉴를 찾아서 클릭합니다.

DART 메뉴

인증키 신청/관리 메뉴로 가서 인증키 신청을 진행하고 로그인 하면 됩니다. 인증키를 신청할 때 사용자를 개인과 기관으로 구분하는데 기관으로 신청 시 입력할 사항들이 늘어나는 반면 공시목록 및 기업개황 조회를 한도제한 없이 사용할 수 있다고 합니다.

인증키 신청/관리

개발가이드를 보면 DART OpenAPI로 조회할 수 있는 데이터 종류들을 살펴볼 수 있습니다. 다음은 DART에서 제공하는 API들의 개발가이드 링크입니다.

여기서는 간단히 예로 DART OpenAPI 사용법을 알아보겠습니다.

DART API는 HTTP GET Method로 데이터 요청을 보냅니다. API마다 지원하는 출력 포멧(Zip 파일, JSON, XML)이 다릅니다. 대부분 JSON과 XML을 지원하고 요청 URL 마지막이 .json, .xml으로 출력포멧에 따라 다릅니다. 여기서는 JSON 포멧 요청 우선적으로 사용하겠습니다.

먼저 고유번호 API로 공시대상회사의 8자리 고유번호를 획득해 보겠습니다.

고유번호 API는 출력포멧이 Zip 파일입니다. 파이썬으로 다음과 같이 데이터를 확인할 수 있습니다.

여기서는 requests로 HTTP 요청을 수행합니다. API 파라미터로 입력해야 하는 crtfc_key는 위에서 발급했던 인증키를 입력하면 됩니다. 데이터가 binary 형태이기 때문에 ByteIO로 읽어주고 Zip 파일로 생성합니다.

import requests
from io import BytesIO
import zipfile
import xmltodict
api = 'https://opendart.fss.or.kr/api/corpCode.xml'
res = requests.get(api, params={'crtfc_key': crtfc_key})
data_xml = zipfile.ZipFile(BytesIO(res.content))

이렇게 하면 공시대상 기업의 고유번호 데이터를 Zip 압축 포멧으로 받을 수 있습니다. Zip 파일에 담겨있는 파일은 리스트는 다음과 같이 확인할 수 있습니다.

z.namelist()
output: ['CORPCODE.xml']

여기서는 편의상 다음과 같이 XML 파일을 dict로 변환했습니다.

import xmltodict
import json
data_xml = z.read('CORPCODE.xml').decode('utf-8')
data_odict = xmltodict.parse(data_xml)
data_dict = json.loads(json.dumps(data_odict))
data = data_dict.get('result', {}).get('list')

이를 위해 xmltodict 라이브러리를 사용했습니다. xmltodict로 XML을 파싱하고 나면 OrderedDict 형식의 결과를 얻을 수 있습니다. 이를 편의상 dict 형식으로 변환하기 위해 JSON dumps/loads 과정을 거쳤습니다.

data를 확인해 보면 공시대상 기업들의 고유번호와 주식 종목코드를 확인할 수 있습니다.

for item in data:
if item['corp_name'] in ["삼성전자", "SK하이닉스", "NAVER"]:
print(item)
output:
{'corp_code': '00126380', 'corp_name': '삼성전자', 'stock_code': '005930', 'modify_date': '20191209'}
{'corp_code': '00266961', 'corp_name': 'NAVER', 'stock_code': '035420', 'modify_date': '20200512'}
{'corp_code': '00164779', 'corp_name': 'SK하이닉스', 'stock_code': '000660', 'modify_date': '20200512'}

DART API는 대부분 공시대학회사의 고유번호를 요청 파라미터로 입력해줘야 하므로 이 데이터를 잘 관리하고 있는 것이 좋습니다.

기업개황 API는 대표자명, 사업자등록번호 등의 기업의 기본 정보를 제공합니다. JSON 포멧 요청 URL은 https://opendart.fss.or.kr/api/company.json이고 다음 두 파라미터를 입력해야 합니다.

  • crtfc_key: 발급받은 인증키
  • corp_code: 공시대상회사 고유번호

crtfc_key에 발급받은 인증키를 입력하고 corp_code에 삼성전자의 기업번호인 00126380를 입력하면 다음과 같은 결과를 얻을 수 있습니다.

res = requests.get('https://opendart.fss.or.kr/api/company.json?crtfc_key=2ff3dd09bbe0e8140dc1941c86ed08b77597b5e5&corp_code=00126380')
item = json.loads(res.text)
print(item)
output:
{'status': '000',
'message': '정상',
'corp_code': '00126380',
'corp_name': '삼성전자(주)',
'corp_name_eng': 'SAMSUNG ELECTRONICS CO,.LTD',
'stock_name': '삼성전자',
'stock_code': '005930',
'ceo_nm': '김기남, 김현석, 고동진',
'corp_cls': 'Y',
'jurir_no': '1301110006246',
'bizr_no': '1248100998',
'adres': '경기도 수원시 영통구 삼성로 129 (매탄동)',
'hm_url': 'www.sec.co.kr',
'ir_url': '',
'phn_no': '031-200-1114',
'fax_no': '031-200-7538',
'induty_code': '264',
'est_dt': '19690113',
'acc_mt': '12'}

그 외의 API들도 이와 비슷한 방법으로 사용할 수 있으므로 이렇게 마무리하겠습니다. 질문이 있으시면 메일 등으로 문의주시면 됩니다.

  • dart-fss 라이브러리를 사용하면 DART에서 쉽게 재무제표를 추출할 수 있습니다.
  • Insomnia는 간편하게 HTTP API를 사용해 볼 수 있는 클라이언트 입니다.