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


전 편에 이어서 포스팅 하도록 하겠습니다.
못 보신 분들을 위해 링크 걸겠습니다.

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

여기서 크롤링이란 무엇일까요?

우리가 흔히 부르는 크롤링(crawling) 혹은 스크래핑(scraping)이라고 하는 것은,
웹 페이지를 그대로 가져와 데이터를 추출해 내는 행위입니다.
이러한 작업을 하는 소프트웨어를 크롤러(crawler)라고 부릅니다.



우리는 종목 코드와 원하는 기간동안의 보고서를 DataFrame으로 저장하여 손 쉽게 핸들링 할 수 있도록 만들었습니다. 지금부터는 보고서에 있는 재무제표를 크롤링 하겠습니다.


STEP 1. 페이지 분석 및 링크 확인

재무제표를 크롤링하기 위해서는 페이지를 분석을 해야합니다.
저는 과거에 위키피디아를 크롤링 해본적이 있습니다.
크롤링을 위해서는 html이나 javascript에 대한 이해가 필요한데, 저도 이 부분은 아는 바가 거의 전혀 없기 때문에 구글링하면서 하나하나 해결해나가도록 하겠습니다.
거듭 강조드리지만 문제를 해결하는 능력을 기르는 것이 중요합니다.

우선 저는 크롬을 사용하기 때문에 크롬의 기준에서 말씀드리겠습니다.
크롬에서 [도구 더 보기] - [개발자 도구]를 선택하면 개발자 도구를 사용할 수 있습니다.
다른 브라우저에서도 비슷한 도구들이 있으니 찾아보시기 바랍니다.


그러면 이런 형태의 창이 나옵니다.
위와 같이 HTML의 형태를 확인했으니 원하는 정보를 뽑아 올 것입니다.

웹 사이트의 데이터를 수집하는데 있어서는 2가지의 단계가 있습니다.

1. 스크래핑(Scraping) : 데이터를 가져오는 작업

2. 파싱(Parsing) : 가져온 데이터를 추출하는 작업

하지만 그 전에 해야 할 것은 바로 웹페이지에 접속하는 것이겠죠.
우리는 재무제표를 스크래핑 하기 전에 우선 재무제표의 url을 알아야합니다.


저기 [Network] 탭이 보이실 겁니다. 누르면 위와 같은 창이 나타납니다.
우측에 네트워크 탭을 선택하고 링크를 누르면 시간초 별로 서버에서 응답하는 목록을 확인할 수 있습니다. 우리는 이 기능을 통해서 url을 알아내도록 하겠습니다.
이제 웹페이지에 있는 재무제표를 누르시면 됩니다.

그러면 위와 같은 반응이 하나 나올 겁니다.
오른쪽 클릭 [Copy] - [Copy link address] 해봅시다.

저는 아래와 같은 주소가 나왔습니다. 


이 url이 재무제표로 넘어가는 url임을 알 수 있습니다.
여기서 우리는 rcpNo는 손쉽게 알 수 있었지만 dcmNo은 알기가 어렵습니다.
우리가 실제로 클릭하는 공시창의 왼쪽 부분의 페이지 소스 코드에는 없었거든요. 

참고로 저는 지금 실제로 하나하나 해결해가면서 포스팅 중입니다. 
미리 해본 것이 아닙니다.
왜 이런 말을 하나면! 사실 여기서 저는 urllib을 선택한 것을 후회했습니다.
왜냐하면 저는 재무제표를 클릭하기 전에는 dcmNo를 알 수가 없다고 생각합니다.
하지만 그걸 지금까지 몰랐습니다. 그래서 urllib으로 간단하게 하려고 했는데,
urllib는 onclick 기능(즉, 클릭해주는 기능)이 서칭해보니까 없는 것 같더라구요. 
(사실 있을수도 있습니다.) 
그래서 저는 과감하게 urllib을 버리고 requests와 lxml과 re 모듈을 사용하겠습니다.
지금까지 따라오시느라 배신감이 드시겠지만, 어쩔 수 없습니다. 
이런 과정들도 다 도움이 될 거라는 생각에 1편은 안 바꾸도록 하겠습니다.

최종 코드는 이렇습니다. (아직 수정 중입니다. 내일 중에 완성 될 듯 싶네요.)
참고로 1편에 썼던 urllib모듈의 메소드들은 requests모듈로 바꿨습니다.
하나하나 비교해보면서 배우시는 것도 좋을 것 같네요.
그러면 차근차근 분석해보도록 하겠습니다. 천천히 따라오세요.


우리는 request모듈의 get()메소드를 사용해서 응답을 요청했습니다.
그 다음 .text로 html코드를 획득한 뒤에
여기서 lxml모듈을 사용합니다.
lxml모듈의 설명은 아래와 같습니다.

lxml comes with a dedicated Python package for dealing with HTML: lxml.html. It is based on lxml's HTML parser, but provides a special Element API for HTML elements, as well as a number of utilities for common HTML processing tasks.

우리는 여기서 fromstring이라는 메소드를 사용 할 것입니다.


fromstring(string):
Returns document_fromstring or fragment_fromstring, based on whether the string looks like a full document, or just a fragment.

그 다음 우리는 Xpath라는 개념에 대해 알아봐야 합니다.

Xpath란?

XPath(XML Path Language)는 W3C의 표준으로 확장 생성 언어 문서의 구조를 통해 경로 위에 지정한 구문을 사용하여 항목을 배치하고 처리하는 방법을 기술하는 언어이다. XML 표현보다 더 쉽고 약어로 되어 있으며, XSL 변환(XSLT)과 XML 지시자 언어(XPointer)에 쓰이는 언어이다. XPath는 XML 문서의 노드를 정의하기 위하여 경로식을 사용하며, 수학 함수와 기타 확장 가능한 표현들이 있다.

XML 예제 문서


  
     name="Wikipedia" launch="2001-01-05">
      
         language="English">en.wikipedia.org
         language="German">de.wikipedia.org
         language="French">fr.wikipedia.org
         language="Polish">pl.wikipedia.org
      
name="Wiktionary" launch="2002-12-12"> language="English">en.wiktionary.org language="French">fr.wiktionary.org language="Vietnamese">vi.wiktionary.org language="Turkish">tr.wiktionary.org
아래의 XPath 식은
/wikimedia/projects/project/@name
모든 project 요소의 name 속성을 선택하고, 아래의 XPath 식은
/wikimedia/projects/project/editions/edition[@language="English"]/text()
모든 영문 Wikimedia 프로젝트의 주소(language 속성이 English인 모든 edition 요소의 문자열)를 선택하고, 아래의 XPath 식은
/wikimedia/projects/project[@name="Wikipedia"]/editions/edition/text()
모든 위키백과의 주소(Wikipedia의 이름 특성을 가진 project 요소 아래에 존재하는 모든 edition 요소의 문자열)를 선택한다.

이런 개념입니다. 저도 자세하게는 모르겠네요. 깊게 알고 싶지도 않습니다.
구글링의 도움을 빌려 코드를 빌려왔습니다. 필요하신 분들은 더 알아보시면 됩니다.

이 다음에는 re라는 파이썬의 기본 모듈을 사용합니다.
이 모듈은 파이썬에서 정규 표현식을 지원하도록 해줍니다.

정규 표현식이란?

정규 표현식(Regular Expressions)은 복잡한 문자열을 처리할 때 사용하는 기법으로, 파이썬만의 고유 문법이 아니라 문자열을 처리하는 모든 곳에서 사용된다. 정규 표현식을 배우는 것은 파이썬을 배우는 것과는 또 다른 영역의 과제입니다.
배울 게 너무 많네요. 우리는 스킵하고 코드만 가져가도록 하죠.

우리는 결국 이러한 과정들을 통해 dcmNo를 구했습니다.
이 부분들이 너무 방대한 분량이라서 이해하기에는 무리가 있습니다.
일단 이런 것들이 있구나 하고 넘어가시면 되겠습니다.

STEP 2. 스크래핑(Scraping)

이제 해당 url에서 우리가 가져오고자 하는 표가 어디에 있는지 확인하겠습니다.
다시 [개발자 도구]에서 이번엔 [Elements] 탭을 선택합니다.
저기 초록색 버튼이 보이시나요?
저 버튼을 누르면 원하는 element를 검사하게 됩니다.
저걸 누른 뒤에 재무제표를 아무데나 눌러봅시다.


여기서 HTML에 대해 간단히 알아보도록 하겠습니니다.

HTML의 구조는 대략 이렇습니다.

    
    
    
        
            Here's a paragraph of text!
            Learn Data Science Online
        
Here's a second paragraph of text! Python
그러면 우리가 앞에서 검사한 element를 볼까요?
td라고 하는 태그에 파란 불이 켜진 것을 확인 할 수 있습니다.
td 옆에 tr tbody table 등 있는 것들은 모두 td의 상위 태그들입니다.

왼쪽에 있을수록 상위 태그이므로 하나하나 눌러서 확인해보면
table이라는 태그가 내가 선택한 표라는 것을 확인할 수 있습니다.
재무제표에는 여러 table들이 있네요.라는 태그를 상속받은 태그를 사용한다는 것을 인지하고 확인해봅시다.



우리가 아까 전에 간단히 알아본 XPath라는 개념을 여기서 다시 사용합니다.
오른쪽 버튼을 누르고 [Copy] - [Copy XPath] 를 눌러서 XPath를 알아봅시다.
규칙성을 확인해보기 위해서 3개 정도를 알아보도록 하겠습니다.
저는 1번째, 2번째, 그리고 12번째 값의 Xpath를 알아보았습니다.

/html/body/table[2]/tbody/tr[2]/td[2]
/html/body/table[2]/tbody/tr[3]/td[2]
/html/body/table[2]/tbody/tr[13]/td[2]

이런 식의 규칙성을 보이고 있네요.
이렇게 웹페이지의 규칙적인 정보는 대부분 아파트와 같은 구조를 가지고 있습니다.
우리는 이 규칙성을 이용해서 컴퓨터에게 데이터에 접근하도록 할 것입니다.









댓글 5개:

  1. 안녕하세요! 크롤링을 보며 많은 도움을 받고있습니다. 데이터를 불러오는 방법에 질문을 드리고자 하는데, json이 아닌 xml을 사용하시는 특별한 이유가 있으신지요..?

    답글삭제
    답글
    1. xml 데이터가 사용하기가 더 편리합니다. R시각화할때도 기본으로 사용하기도하고요.

      삭제
  2. 좋은 정보 정말 감사드립니다!

    답글삭제
  3. 혹시 코드 완성본이 있을까요? 코드를 적용했을때 name 'parser' is not defined 에러가 뜨는데 parser에 대한 정의를 내리지 않아서 인가요ㅠㅠ?

    답글삭제
  4. 좋은 정보 감사합니다.
    전체 상장사 재무제표를 한번에 다운받을수도 있을까요?

    감사합니다.

    답글삭제