전자공시시스템(DART) 오픈API 이용하여 재무제표 크롤링하기 with 파이썬 (1)



오픈API란?

오픈 API(Open Application Programming Interface, Open API, 공개 API)는 누구나 사용할 수 있도록 공개된 API를 말한다.

구글맵이 대표적인 예이다. 지도 서비스 및 다양한 서비스들에서 시도되고 있으며 누구나 접근하여 사용할 수 있다는 장점이 있다. 메타블로그들도 오픈 API를 사용하여 만드는 것들이다.

전자공시시스템이란?

전자공시시스템(DART ; Data Analysis, Retrieval and Transfer System)은 상장법인 등이 공시서류를 인터넷으로 제출하고, 투자자 등 이용자는 제출 즉시 인터넷을 통해 조회할 수 있도록 하는 종합적 기업공시 시스템입니다.



현재 DART에서는 검색API기업개황API, 2가지API를 제공 중입니다.
개발가이드를 참고 하실 분들은 아래 링크를 이용 바랍니다.

현재 직접적으로 재무제표를 제공하는 API는 없기 때문에 검색API를 통해 재무제표 정보를 확인 하도록 하겠습니다.

우선 DART에 접속해서 인증키를 신청하시면 아래와 같이 발급 받을 수 있습니다.
이 인증키는 개인마다 다른 번호로 발급됩니다.
개인용은 일일 사용량은 10,000건으로 제한 되어 있습니다.


API를 이용하여 정보를 요청 할 때, 형식에 맞게 url을 만들어 요청하면 됩니다.
우선 url에 본인이 확인하고 싶은 종목의 종목 코드를 넣으면 됩니다.

저는 제가 지금 보유중인 기업은행 종목코드(024110)를 넣겠습니다.

우리가 재무제표를 보기 위해 확인해야 할 공시는 정기공시입니다.
아래는 정기공시에서도 우리가 사용할 정기공시의 종류입니다.

1. 사업보고서
기업들의 연간 결산에 대한 내용들을 담은 보고서.
사업연도말 경과 후 90일 이내에 사업보고서를 금융위원회와 한국거래소에 제출. (즉, 12월 결산 기업은 3월31일 이내)

2. 분기보고서
분기·반기보고서의 기재사항은 사업보고서를 표준으로 함.
* 분기 결산후 45일 이내 고시. (1분기 실적 결산 후면 4월 15일까지)

3. 반기보고서
반기보고서는 사업연도가 1년인 상장법인이나 코스닥 등록법인이 그 사업연도 개시일부터 6개월째 되는 날에 가결산을 하여 재무상태와 6개월 동안의 경영성과를 요약한 서류.
* 반기보고서는 반기 결산기 말로부터 45일 내에 제출

위의 3가지 보고서를 토대로 재무제표를 크롤링 하도록 하겠습니다.

검색API는 xml 응답과 json 응답을 받을 수 있습니다.
요청 주소에 따라 달라지는데 우리는 친숙한 xml 형식으로 되어있는 xml 응답 주소에
요청 하도록 하겠습니다.


그 다음에 우리는 요청 변수가 어떤 것들이 있는지 확인 해보도록 하겠습니다.
우리가 저 주소에 요청할 수 있는 변수는 아래와 같습니다. (개발가이드 참고)


필수라고 되어있는 인증키는 당연히 필수로 입력해야 합니다.
그래서 지금 우리가 사용할 변수는 

인증키 auth
종목코드  crp_cd
검색종료 접수일자 end_dt
검색시작 접수일자 start_dt
공시종류 dsp_tp
세부공시종류 bsn_tp
정도입니다.
위에 명시되어 있는 변수 형태로 코드를 입력한뒤 응답 요청하도록 하겠습니다.
코드는 아래와 같습니다.





과정은 이렇습니다. 천천히 이해하면서 따라오시기 바랍니다.

STEP 1. 필요한 모듈 import

STEP 2. 인증키, 종목 코드, 시작 날짜 변수화

STEP 3. 요청 변수를 조합하여 요청할 url 변수화

STEP 4. url연 뒤에 읽어오기

우리는 from urllib.request import urlopen 을 통해 urllib.request에 있는 urlopen을 import 했습니다. urllib은 URL handling modules입니다. 
우리가 사용한 urllib.request는 urllib.request for opening and reading URLs이라고 설명되어 있습니다. 쉽게 말해 스타크래프트 확장팩과 같은 구조라고 보시면 됩니다.

아래는 urlopen 메소드의 구조입니다.
이런 문서를 읽을 줄 알아야 파이썬의 진가가 발휘되므로 영어에 익숙해 지셔야 합니다.
(https://docs.python.org/3/library/urllib.request.html#module-urllib.request 참조)


urllib.request.urlopen(urldata=None[timeout]*cafile=Nonecapath=Nonecadefault=Falsecontext=None)

Open the URL url, which can be either a string or a Request object.
If the URL does not have a scheme identifier, or if it has file: as its scheme identifier, this opens a local file (without universal newlines); otherwise it opens a socket to a server somewhere on the network. If the connection cannot be made the IOError exception is raised. If all went well, a file-like object is returned. This supports the following methods: read()readline()readlines()fileno(),close()info()getcode() and geturl(). It also has proper support for the iterator protocol. One caveat: the read() method, if the size argument is omitted or negative, may not read until the end of the data stream; there is no good way to determine that the entire stream from a socket has been read in the general case.

위에를 보시면 a file-like object 가 리턴됩니다. 여기서 우리는 read() 메소드를 사용하여  객체를 읽어올 것입니다. (위의 메소드 설명들은 파이썬2버전의 문서에서 가져왔습니다. 한 문서에 모든 것들이 다 설명되어 있지 않은 경우가 있기 때문에 검색하는 능력을 길러야 합니다.)

STEP 5. 데이터 뽑아오기(정제과정)

우리가 위에서 import한 bs4의 BeautifulSoup의 설명은 아래와 같습니다.
Beautiful Soup is a Python library for pulling data out of HTML and XML files.

Beautiful Soup에는 파싱하는 여러가지 방법들이 있습니다. 

This table summarizes the advantages and disadvantages of each parser library:
ParserTypical usageAdvantagesDisadvantages
Python’s html.parserBeautifulSoup(markup, "html.parser")
  • Batteries included
  • Decent speed
  • Lenient (as of Python 2.7.3 and 3.2.)
  • Not very lenient (before Python 2.7.3 or 3.2.2)
lxml’s HTML parserBeautifulSoup(markup, "lxml")
  • Very fast
  • Lenient
  • External C dependency
lxml’s XML parserBeautifulSoup(markup, "lxml-xml")BeautifulSoup(markup, "xml")
  • Very fast
  • The only currently supported XML parser
  • External C dependency
html5libBeautifulSoup(markup, "html5lib")
  • Extremely lenient
  • Parses pages the same way a web browser does
  • Creates valid HTML5
  • Very slow
  • External Python dependency


여러 장단점들이 있지만 우리는 html.parser를 사용하겠습니다.
만들어진 xmlsoup 객체는 정보가 list tag단위로 저장되게 됩니다.
우리는 이 객체를 list단위로 슬라이싱하여 저장 한 뒤에 for문을 사용하여 
한 줄씩 dataframe으로 저장하고 합치겠습니다.

STEP 6. 파싱한 데이터를 데이터프레임으로 변환 

pandas의 dataframe이라는 데이터형식은 데이터 핸들링을 용이하고 빠르게 만들어줍니다.
이 부분은 방대한 양이므로 따로 공부바랍니다. 반드시 필요한 부분입니다.
빈 DataFrame을 만든 뒤에 BeautifulSoup의 findAll() 메소드를 사용합니다.
(높은 버전에서는 find_all()로 바뀐 것 같습니다.)

find_all()의 시그니처입니다.
find_all(nameattrsrecursivestringlimit**kwargs)
The find_all() method looks through a tag’s descendants and retrieves all descendants that match your filters. 


우리는 list로 나뉜 정보를 모두 찾은 뒤에 차곡차곡 DataFrame에 넣었습니다.
각 컬럼마다 보고서가 한 개씩 들어있는 구조가 됩니다.

STEP 7. 인덱스 수정 

현재 print(data)를 해보면 컬럼 인덱스가 0으로 되어 있는 것을 확인 하실 수 있습니다.
이것을 pandas의 reset_index()메소드를 사용하여 리셋 하겠습니다.

OPTIONAL STEP. 원하는 보고서 오픈

우리는 webbrowser라는 모듈을 import했었습니다.
아래는 설명입니다.
The webbrowser module provides a high-level interface to allow displaying Web-based documents to users.
우리는 만들었던 DataFrame을 이용해 새로운 user_url이라는 url을 만들어서 이를 이용하겠습니다. 
webbrowser의 open메소드를 사용하면 간편하게 웹페이지를 오픈 할 수 있습니다.

다음 편에서는 보고서에서 재무제표에 해당하는 부분을 크롤링 해오도록 하겠습니다.

======

참고 웹사이트 : http://tariat.tistory.com/31 (테리엇의 디지털 놀이터)

0 개의 댓글:

댓글 쓰기