[dart api 2] 기업공시시스템 open api로 매출총이익률 계산하기 - #dart#기업공시시스템#open api#API#다트

2017. 12. 23. 22:42

오늘은 전에 다뤘던 dart(전자공시스템) 오픈API에 대해서 추가 작업을 해 보려고 합니다. 이전 글에서 오픈API를 이용해서, 반기보고서가 있는 url을 수집하였습니다. 그리고 python webbrowser 함수를 이용하여, 웹브라우저에서 보는 작업을 했었습니다.

(참고: 기업공시시스템 open api 사용하기)

  

이번에는 좀 더 나아가서, 반기보고서에 있는 값들을 이용해서 매출총이익률을 계산해 보려고 하는데요. 그러기 위해서 반기보고서에 있는 재무재표를 크롤링을 하여 파이썬 DataFrame으로 저장하고, 매출총이익률을 계산해 보도록 하겠습니다.



제목



관련 글 보기

맥(mac) 메모 기능 200% 활용하기

롯데카드 챗봇 로카 사용 후기

cheat sheet 참고 자료 알아보기



먼저 반기보고서에 있는 재무제표를 크롤링해 보도록 하겠습니다.

  

1. 반기 보고서에서 재무제표의 url을 확인한다.

한미케미칼_제무제표

(한솔케미칼 반기 보고서의 "재무제표")



위에서 보시는 반기보고서에 있는 재무제표의 페이지 url을 알아야 하는데요. 사실 이런 작업은 html이나 javascript를 잘 모르면 하기가 어렵습니다. 보통 이 내용을 확인하기 위해, 웹브라우저의 개발자 도구를 활용하여 html과 javascript를 해석(?)해야 하기 때문입니다. 저도 html과 javascript를 정말 조금 아는데요. 조금 아는 지식으로 해석하려고 하니, 할 때마다 고생이네요. ㅎㅎㅎ

(웹브라우저에서 개발자 도구 사용하려면, 크롬은 메뉴에 [보기] - [개발자 정보] - [개발자 도구]로 가시면 됩니다.)


html을 참조해서 보게 되면, 재무제표로 넘어가는 url은  "http://dart.fss.or.kr/report/viewer.do?rcpNo=20170811001153&dcmNo=5746981&eleId=15&offset=297450&length=378975&dtd=dart3.xsd"인 것을 알 수 있습니다. 


위 url을 브라우저 주소창에 입력하시면 아래와 같이 재무제표만을 보실 수 있습니다.

  

재무상태표

('반기보고서'에서 '재무제표'만 연 화면 모습) 





2. 재무제표를 크롤링합니다.


이제 해당 url에서 우리가 가져오고자 하는 재무제표가 어디에 있는지 확인해야 합니다. 참고로 html에서 표는 <table>이라는 태그로 되어 있기 때문에, 해당 tag를 위주로 확인합니다. 

  

여기까지 code를 확인해 보도록 하겠습니다.



url2="http://dart.fss.or.kr/report/viewer.do?rcpNo=20170811001153&dcmNo=5746981&eleId=15&offset=297450&length=378975&dtd=dart3.xsd"

report=urlopen(url2)
r=report.read()
xmlsoup=BeautifulSoup(r,'html.parser')
body=xmlsoup.find("body")
table=body.find_all("table")
p = parser.make2d(table[3])

sheet = pd.DataFrame(p[2:], columns=["구분","38기반기_3개월","38기반기_누적","37기반기_3개월","37기반기_누적"])



내용을 간단하게 설명드리면, 'r=report.read()'에서 url의 html 정보를 읽어옵니다. 그리고 BeautifulSoup을 이용하여 html형식으로 파싱을 합니다. 그리고 body tag의 내용을 찾습니다. 다음에 body 태그 안에 table태그를 찾습니다.

제가 원하는 제무상태표는 3번째 테이블이므로, 세번째 테이블 가져와서 DataFrame으로 변형합니다.



3. 원하는 지표값을 산출해 봅니다.

여기서는 간단하게 매출총이익률을 계산해 보고자 합니다. 매출총이익률을 계산하는 방법은 '매출총이익 / 매출액 *100'입니다. 매출총이익은 '매출액 - 매출원가' 입니다. DataFrame에 값이 다 있기 때문에, 계산하는 것은 간단합니다. 다만, 현재 String값으로 입력되어 있기 때문에 이 값을 int나 float로 변경해 주어야 합니다.



sheet["38기반기_3개월"]=sheet["38기반기_3개월"].str.replace(",","")
sheet["temp"]=sheet["38기반기_3개월"].str[0]

sheet.ix[sheet["temp"]=="(","38기반기_3개월"]=sheet["38기반기_3개월"].str.replace("(","-")
sheet["38기반기_3개월"]=sheet["38기반기_3개월"].str.split(")").str[0]
sheet.ix[sheet["38기반기_3개월"]=="","38기반기_3개월"]="0"
sheet["38기반기_3개월"]=sheet["38기반기_3개월"].astype(int)



string을 int로 변경하였는데요. 실제 변경하는 작업은 마지막에 있습니다. 다만, 재무제표 상에 마이너스인 값이 (989,000,000)과 같이 괄호를 사용한 값이기 때문에, -989000000으로 바꿔줘야 합니다. 그래야 int로 변경할 때 에러가 나지 않습니다.



sale = sheet[sheet["구분"]=="매출액"].iloc[0,1]
sale_cost = sheet[sheet["구분"]=="매출원가"].iloc[0,1]
sale_profit_ratio=(sale-sale_cost)/sale*100

# round는 반올림
sale_profit_ratio=round(sale_profit_ratio,1)
print("매출총이익률은 "+str(sale_profit_ratio)+"% 입니다")



int로 변환해 준 뒤에는 각각의 항목값들을 이용하여 매출총이익률을 구해 줍니다. 계산하고 나면 소수점이 길게 나오기 때문에, 예쁘게 출력하기 위해 반올림을 해 줍니다.



작업을 마치고 나니 아래와 같이 한솔케미칼의 반기재무제표의 매출 총이익률이 나왔습니다.


매출총이익률은 25.1% 입니다


  

25.1%면 매출총이익률이 높은 것인지 낮은 것인지 쉽게 감이 오지는 않네요. 보통 이런 경우에 같은 산업군이나 다른 회사들과 비교하게 되는데요. 다음에는 하나의 회사가 아니라 여러 개의 회사에 대해 같은 지표를 산출해 보고자 합니다. 그러기 위해서 코드를 함수 형태로 변환하고 for문을 이용해서 다수의 회사에 대해 작업을 해 보도록 하겠습니다.

다수의 기업에 매출총이익률을 계산한 작업은 아래 글을 참조하시면 됩니다.



댓글()
  1. 11 2018.06.02 17:41 댓글주소  수정/삭제  댓글쓰기

    제무제표로 넘어가는 url 어떻게 조회하셨나요??????

    • Favicon of https://tariat.tistory.com BlogIcon 테리엇 2018.06.03 21:08 신고 댓글주소  수정/삭제

      재무제표로 넘어가는 url은 html페이지에서 찾기가 어렵습니다. jsp에 대한 지식이 필요할 듯한데, 저도 jsp는 잘 몰라서요.
      저같은 경우에는 코드를 보고 파라미터를 추정해서 이것저것 테스트 해보고 알아냈습니다.
      감사합니다.

  2. 익명 2019.12.16 19:11 댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • Favicon of https://tariat.tistory.com BlogIcon 테리엇 2019.12.17 22:40 신고 댓글주소  수정/삭제

      패키지가 import가 안 된 것 같습니다. html의 표를 판다스 데이터프레임으로 바꿀 때, html_table_parser패키지를 사용하거든요. html_table_parser패키지를 설치하시고, 위에 from html_table_parser import parser_functions as parser를 추가하시면 될 거 같습니다. html_table_parser를 설치하면 beautifulsoup이 안 될 수 있습니다. 이 때는 beautifulsoup을 지우고 다시 설치하시면 됩니다.
      html_table_parser에 대한 내용은 아래 포스팅을 참고해보세요.
      https://tariat.tistory.com/793