Post List

2018년 8월 3일 금요일

R에서 네이버 금융 재무제표 및 밸류에이션 크롤링




먼저 NAVER 금융 (https://finance.naver.com) 에 접속하여
원하는 종목을 검색한 후,
종목분석을 선택합니다.



그 후, 크롬 개발자도구 화면을 연 후 (F12)
하단 Financial Summary 항목의 
'연간' 을 선택합니다.




연간기준 재무제표로 바뀌며
cF1001.aspx?,,,,, 항목이 생성됩니다.

즉, 네이버 금융의 재무제표 항목은
해당 사이트의 내용을 따와서 
사이트 내에서 보여주는 방식입니다.


Request URL 에 있는 주소에 접속합니다.

https://companyinfo.stock.naver.com/v1/company/ajax/cF1001.aspx?cmp_cd=005930&fin_typ=0&freq_typ=Y




해당 데이터를 R로 크롤링하는 과정은 다음과 같습니다.



library(rvest)
library(httr)

data_fs = c()
data_value = c()

먼저 크롤링에 필요한 패키지인
rvest와 httr을 불러옵니다.

그 후, 재무제표와 밸류지표가 들어갈 빈 변수를 만들어 줍니다.



url = "https://companyinfo.stock.naver.com/v1/company/ajax/cF1001.aspx?cmp_cd=005930&fin_typ=0&freq_typ=Y"
data = GET(url)
data_fs = read_html(data) %>%
  html_table(fill = TRUE) %>%
  data.frame()

위 주소를 url에 저장해준 후
GET() 함수를 통해 데이터를 요청합니다.

그 후, read_html() 함수를 통해 HTML 정보를 불러온 후,
html_table() 함수를 통해 테이블 정보만 읽어옵니다.

셀병합이 된 경우 html_table()이 오류가 나므로
fill = TRUE 변수 추가를 통해
셀 병합을 풀어주도록 합니다.

그 후 data.frame() 함수를 통해
데이터 프레임 형태로 바꾸어 줍니다.

이 모든 과정은 파이프 오퍼레이터 (%>%)를
이용하여 줍니다.




data_fs 변수를 확인해보면
홈페이지의 내용이 다 잘들어 와있습니다.

이제 간단한 클랜징 작업만 해주면 됩니다.


colnames(data_fs) = data_fs[1, ]
colnames(data_fs) = substr(colnames(data_fs),1,7)
data_fs = data_fs[-1, ]

rownames(data_fs) = data_fs[, 1]
data_fs = data_fs[, -1]


첫번째 행을 열이름으로 만든 후,
substr() 함수를 통해 1에서 7까지 글자, 즉
YYYY/MM 부분만을 남겨줍니다.
그 후 첫번째 행은 삭제합니다.

마찬가지로 첫번째 열을 행이름으로 만들어 준 후,
첫번째 열은 삭제합니다.



깔끔하게 정리가 되었습니다.


이번에는 밸류에이션을 크롤링하도록 하겠습니다.
개발자도구 화면을 연 상태에서

종목분석의 투자지표를 클릭합니다.

이 중 cF4002.aspx?cmd... 부분이
해당 페이지의 데이터를 가지고 오는 부분입니다.





Request URL 에 있는 주소에 접속합니다.

https://companyinfo.stock.naver.com/v1/company/cF4002.aspx?cmp_cd=005930&frq=0&rpt=1&finGubun=MAIN&frqTyp=0&cn=




구조가 망측하군요.
제이슨 형태입니다.

다행히 R에서도 제이슨 형태를 쉽게 긁어올 수 있습니다.



library(jsonlite)

url = "https://companyinfo.stock.naver.com/v1/company/cF4002.aspx?cmp_cd=005930&frq=0&rpt=5&finGubun=MAIN&frqTyp=0&cn="
data  = fromJSON(url)



제이슨 형태 크롤링에 필요한 jsonlite 패키지를 불러옵니다.

그 후 위 주소를 url에 저장해준 후
fromJSON() 함수를 통해 데이터를 요청합니다.


data에는 리스트 형태로 총 4개의 리스트가 저장되며
이 중 첫번째 리스트는 연도,
두번째 리스트는 구체적인 데이터 입니다.





data = data[[2]] %>% data.frame()
data_table = cbind(data$DATA5)

rownames(data_table) = data$ACC_NM


데이터에 해당하는 2번째 리스트를 데이터 프레임 형태로 바꿉니다.

그 후, 예상치가 아닌 최근결사년도(2017년) 데이터인
DATA5 열을 선택합니다.

행이름은 ACC_NM 열을 선택해 줍니다.

data_table에는 다음과 같은 2017년 데이터가 저장됩니다.






type = c("PER", "PBR", "PCR", "PSR")
data_value = data_table[sapply(type, function(x) {which(rownames(data_table) == x)}), ]


이 중 우리가 선택하고자 하는 지표를
type 변수에 저장합니다.

그 후 sapply 함수를 통해 data_table의 행 이름 중 
type과 같은 인덱스를 선택 한 후,
이에 해당하는 행을 data_table에서 뽑아냅니다.




밸류 지표만이 선택됩니다.

물론 타 지표를 뽑고 싶으면
type 변수에 해당 변수를 입력하면 됩니다.

댓글 5개:

  1. 연달아 좋은내용 무료로 공개 감사드립니다

    답글삭제
  2. https://companyinfo.stock.naver.com/v1/company/ajax/cF1001.aspx?cmp_cd=005930&fin_typ=0&freq_typ=Y
    오류가 나네요..

    답글삭제
    답글
    1. 다 막아 버려서 동적 크롤링해야 긁어오겠네요..

      삭제
    2. 혹시 동적 크롤링은 어떻게 접근해야 할지 알려주실 수 있을까요? 감사합니다.

      삭제
    3. 셀레니움 써서 하면되는데, 셋팅해야 될게 너무 많아서 저는 잘 쓰지 않습니다..

      삭제