본문 바로가기
python/주식

python - 다트.전자공시 Open API 활용(3), 공시대상회사 추출 및 가공 ( xml to dict - xmltodict library)

by 맑은안개 2020. 3. 7.

전 블로그에서 전자공시 OPEN API를 사용하여 공시대상회사를 XML 포맷으로 가공하였다. xmltodict library를 사용하여 XML을 Python dictionary 타입으로 변경하고 추후에는 대상데이터를 pandas로 변환해본다.

 

관련 포스트 시리즈

1. Install Library

pip install xmltodict

xmltodict는 xml을 python dictionary 포맷으로 컨버전해주는 외부 유틸라이브러리 이다.

https://github.com/martinblech/xmltodict

 

2. Source code

from urllib.request import urlopen # HTTP 요청처리
from zipfile import ZipFile        # 공시회사정보 zipfile 처리
from io import BytesIO             # stream 데이터를 메모리에 적재
import os                          # 현재 디렉토리 정보를 얻기 위해
import xmltodict                   # xml을 dict로 파싱
from pathlib import Path           # file 존재유무 체크 유틸
def bind_params(params : dict):
    url_params = []
    for key in params:
        url_params.append(key + '=' + params[key])
    return url_params

def has_corpfile():
    dirpath = os.getcwd()

    if Path(dirpath + '\CORPCODE.xml').is_file():
        return True
    else:
        return False

    # 파일존재 체크 다른 방법들..
    # if os.path.isfile(dirpath + '\CORPCODE.xml'):
	#     return True
    # else:
    #     return False
    # try:
    #     open(dirpath + '\CORPCODE.xml', 'r')
    #     return True
    # except FileNotFoundError:
    #     return False

def get_corp_xml(url, params):

    if has_corpfile():
        dirpath = os.getcwd()
        return open(dirpath + '\CORPCODE.xml', 'r').read()
    else:
        url = url + '&'.join(bind_params(params))
        resp = urlopen(url)

        # zip으로 저장할경우
        # f = open( 'corpCode.zip', 'wb' )
        # f.write(resp.read())
        # f.close()

        # zip파일내용을 풀어 저장한다.
        zipfile = ZipFile(BytesIO(resp.read()))
        print(zipfile.namelist())
        for name in zipfile.namelist():
            z = zipfile.open(name)  
            with open(name, 'w') as codefile:
                for l in z.readlines():
                    codefile.write(l.decode()) 
        dirpath = os.getcwd()
        return open(dirpath + '\CORPCODE.xml', 'r').read()

""" Biz Start """

url = 'https://opendart.fss.or.kr/api/corpCode.xml?'
params = {
  'crtfc_key':'Insert your crtfc_key', # API 인증키
}

corp_xml = get_corp_xml(url, params)

has_corpfile() 는 받아온 Zipfile이 존재하는 경우 API 중복 호출을 피하기 위해 설계되었다. 파일의 존재유무를 체크 하는 방법은 아래 블로그를 참조한다.

https://youngwonhan-family.tistory.com/9

 

python - 디렉토리에 파일존재 유무 체크 ( open, os.path, pathlib )

앞 전에 살펴본 '전자공시 시스템' OPEN API 를 사용하여 기업정보를 xml 파일로 저장하고 읽는 과정을 살펴 보았다. 참조 : https://youngwonhan-family.tistory.com/6 python - 전자공시 OPEN API, HTTP로 얻은..

youngwonhan-family.tistory.com

 

위 소스코드의 결과는 다음과 같다. ( 콘솔로 프린트 하는경우 양이 많으므로 유의할 것 )

<result>
	....
	<list>

        <corp_code>00434438</corp_code>

        <corp_name>KTB에이플러스2호혼합형사모펀드</corp_name>

        <stock_code> </stock_code>

        <modify_date>20170630</modify_date>

    </list>

    <list>

        <corp_code>00286877</corp_code>

        <corp_name>비비앤씨</corp_name>

        <stock_code> </stock_code>

        <modify_date>20170630</modify_date>

    </list>
    ....
</result>

위 XML 포맷을 Dictionary로 변환하기 위해 xmltodict의 parse 함수를 사용한다.

corp_dict = xmltodict.parse(corp_xml)

print(type(corp_dict))

print(corp_dict)

OUTPUT

<class 'collections.OrderedDict'>

....
OrderedDict([('corp_code', '00215824'), ('corp_name', '현대화섬'), ('stock_code', None), ('modify_date', '20170630')]), OrderedDict([('corp_code', '00409380'), ('corp_name', '미래에셋
오리엔탈주식혼합형펀드'), ('stock_code', None), ('modify_date', '20170630')]), OrderedDict([('corp_code', '00471730'), ('corp_name', '태양약품'), ('stock_code', None), ('modify_date', '20170630')])
....

- OrderedDict 는 순서가 있는 dictionary 이다. Regualr Dict와의 차이점은 아래 사이트 참고

https://pymotw.com/2/collections/ordereddict.html

 

OrderedDict - Python Module of the Week

OrderedDict An OrderedDict is a dictionary subclass that remembers the order in which its contents are added. import collections print 'Regular dictionary:' d = {} d['a'] = 'A' d['b'] = 'B' d['c'] = 'C' d['d'] = 'D' d['e'] = 'E' for k, v in d.items(): prin

pymotw.com

Dictionary로 변환해 성공했다. 마지막으로 대상데이터 중 종목코드(stock_code)가 None이 아닌 대상만 추출해보자. 

# reulst > list 추출
corp_list = corp_dict['result']['list']

# stock_code가 None이 아닌 대상만 다시 추출한다.
corp_list_has_stockcode = [x for x in corp_list if x['stock_code'] is not None]

print(len(corp_list_has_stockcode))

OUTPUT

3179

블로그 작성일 기준 3179개의 종목코드를 갖는 회사가 추출되었다.

 

다음 장에는 추출된 상장회사 목록을 활용하여 콘솔에서 회사명을 입력받아 회사의 기본정보를 추출하는 대화형 프로그래밍을 개발해보도록 한다. 

 

반응형