본문 바로가기

API

[전자공시 Dart API] 배당률 높은 회사 리스트 가져오기

반응형

전자공시 Dart API의 주요사항보고서 > 배당에 관한 사항 데이터를 이용해서

배당률이 높은 회사 정보를 가져와 보겠습니다.

 

1. 가입 및 인증키 확인(Skip 가능)

2. 전체 회사리스트 수집

3. 배당률 정보 수집

 

1. 가입 및 인증키 확인(Skip 가능)

https://yenpa.tistory.com/23

 

[전자공시 Dart API] 가입 및 인증키(API Key) 확인하기

1. 사이트 가입 2. 인증키(API Key) 확인하기 1. 사이트 가입 사이트에 접속합니다. https://opendart.fss.or.kr/ 시스템 점검으로 모든 서비스 이용이 일시적으로 중단되어니 양해 부탁드립니다. 시스템 점

yenpa.tistory.com

 

2. 전체 회사리스트 수집

전자공시 API의 공시정보 > 고유번호를 이용해서 전체 회사리스트를 다운받아

압축을 해제하고 결과를 DataFrame에 저장하는 코드입니다.

path는 본인의  PC에 저장하고 싶은 Directory를 지정합니다.

import io
import zipfile
import requests
from xml.etree.ElementTree import parse
import pandas as pd

crtfc_key='YOUR_APIKEY'
#회사정보 가져오기
#임의로 'E:/' 로 설정 및 다운로드 파일 corpcode.zip으로 설정
path='E:/'
filename='corpcode.zip'

url = 'https://opendart.fss.or.kr/api/corpCode.xml'
params = {
    'crtfc_key': crtfc_key,
}
results=requests.get(url, params=params)

file = open(path+filename, 'wb')
file.write(results.content)
file.close()

zipfile.ZipFile(path+filename).extractall(path)

tree = parse(path + 'CORPCODE.xml')
root = tree.getroot()
li=root.findall('list')
corp_code,corp_name,stock_code,modify_date=[],[],[],[]
for d in li:
    corp_code.append(d.find('corp_code').text)
    corp_name.append(d.find('corp_name').text)
    stock_code.append(d.find('stock_code').text)
    modify_date.append(d.find('modify_date').text)
corps_df = pd.DataFrame({'corp_code':corp_code,'corp_name':corp_name,
         'stock_code':stock_code,'modify_date':modify_date})

corps_df = corps_df.loc[corps_df['stock_code']!=' ',:]

결과를 zip으로 저장하고 압축을 해제합니다.

url = 'https://opendart.fss.or.kr/api/corpCode.xml'
params = {
    'crtfc_key': crtfc_key,
}
results=requests.get(url, params=params)

file = open(path+filename, 'wb')
file.write(results.content)
file.close()

xml파일의 내용을 DataFrame으로 저장합니다. stock_code가 없는 데이터는 제외하겠습니다.

corps_df = pd.DataFrame({'corp_code':corp_code,'corp_name':corp_name,
         'stock_code':stock_code,'modify_date':modify_date})

corps_df = corps_df.loc[corps_df['stock_code']!=' ',:]

 

3. 배당률 정보 수집

삼성전자 코드로 배당에 관한 사항 정보를 가져와 보겠습니다.

corp_code='00126380'
bsns_year=2021
reprt_code='11011' 
#1분기보고서 : 11013, 반기보고서 : 11012, 3분기보고서 : 11014, 사업보고서 : 11011

url = 'https://opendart.fss.or.kr/api/alotMatter.json'
params = {
    'crtfc_key': crtfc_key,
    'corp_code' : corp_code,
    'bsns_year' : str(bsns_year),
    'reprt_code' : reprt_code,
}

results = requests.get(url, params=params).json()
results

결과들 중 오늘 가져올 현금배당 수익률 데이터가 확인이 됩니다.

삼성전자의 경우는 우선주와 보통주가 있는 것을 알수 있습니다.

 

반응형

 

 

그럼 corp_df 수집한 회사리스트에서 3494개에서 800개 대한 결과를 가져와 보겠습니다.

import time

result_all=pd.DataFrame()

print('총 회사수는 : ' + str(corps_df.shape[0]))

# 수집한 회사에 대해서 for문.
for i, r in corps_df.iterrows():
    if i == 800:
        break
    
    #없으면 어느 시점에서 에러발생
    time.sleep(0.03)
    
    print('i = ' + str(i))
    corp_code=str(r['corp_code'])
    bsns_year=2021
    reprt_code='11011' 
    #1분기보고서 : 11013, 반기보고서 : 11012, 3분기보고서 : 11014, 사업보고서 : 11011

    url = 'https://opendart.fss.or.kr/api/alotMatter.json'
    params = {
        'crtfc_key': crtfc_key,
        'corp_code' : corp_code,
        'bsns_year' : str(bsns_year),
        'reprt_code' : reprt_code,
    }

    results = requests.get(url, params=params).json()
    print(results)
    # 응답이 정상 '000' 일 경우에만 데이터 수집
    if results['status'] == '000':
        for result in results['list']:
            se=result['se']

            print(se)
            # 현금배당수익률(%) 데이터만 수집
            if se == '현금배당수익률(%)':
                result_dic={}
                result_dic['se']=se
                result_dic['rcept_no']=result['rcept_no']
                result_dic['corp_name']=result['corp_name']
                if 'stock_knd' in test:
                    result_dic['stock_knd']=result['stock_knd']
                else:
                    result_dic['stock_knd']='보통주'
                result_dic['thstrm']=result['thstrm'] #당기
                result_dic['frmtrm']=result['frmtrm'] #전기
                result_dic['lwfr']=result['lwfr'] #전전기
                result_df = pd.DataFrame(result_dic, index=[0])
                
                print(result_df)

                result_all = pd.concat([result_all,result_df])

회사들에 대한 for문입니다.

for i, r in corps_df.iterrows():

for문 마다의 Delay를 주는건데 없으면 어느 시점에서 에러가 발생해서 넣었습니다.

3490개가 돌아가는데 에러가 중간에 발생하는 경우가 많습니다.

전체가 아닌 500 개 단위로 나누어 수집하는것을 추천합니다.

time.sleep(0.05)

결과에서 현금배당수익률(%) 부분만 따로 저장했습니다.

# 현금배당수익률(%) 데이터만 수집
if se == '현금배당수익률(%)':
    result_dic={}
    result_dic['se']=se
    result_dic['rcept_no']=result['rcept_no']
    result_dic['corp_name']=result['corp_name']
    if 'stock_knd' in test:
        result_dic['stock_knd']=result['stock_knd']
    else:
        result_dic['stock_knd']='보통주'
    result_dic['thstrm']=result['thstrm']
    result_dic['frmtrm']=result['frmtrm']
    result_dic['lwfr']=result['lwfr']
    result_df = pd.DataFrame(result_dic, index=[0])

    result_all = pd.concat([result_all,result_df])

보통주/우선주 정보가 없는 회사에서는 에러가 발생해 없는 경우는 공란으로 두었습니다.

if 'stock_knd' in test:
    result_dic['stock_knd']=result['stock_knd']
else:
    result_dic['stock_knd']=''

2021년의 사업보고서 기준으로 데이터를 수집했고 아래의 column들의 정보로

전년도 전전년도인 2020년, 2019년도의 데이터의 확인이 가능합니다.

result_dic['thstrm']=result['thstrm'] #당기
result_dic['frmtrm']=result['frmtrm'] #전기
result_dic['lwfr']=result['lwfr']     #전전기

출력 Parameter확인

그럼 800개에 대한 결과를 보겠습니다.

전체 3493개의 회사에 대한 결과와는 다르니 참고 부탁드립니다.

현금배당 수익률 정보가 전체 회사에 있는 것은 아니네요.

현금배당 수익률 상위로 정렬한 결과입니다.

#배당있는회사만 수집
thstrm=result_all.loc[result_all['thstrm']!='-',:]
thstrm.sort_values('thstrm', ascending=False).head(10)

 

 

전체 3490개의 데이터 수집시 에러가 발생하는 부분은 조금 아쉽습니다.

time.sleep 조건을 수정하던 일정 회사수 단위로 데이터를 수집 하던 수정이 필요할 것 같습니다.

 

이상으로 현금배당 수익률 데이터를 가져와 봤습니다. 

반응형