출처:
퀀트투자쿡북 / 저자: 이현열: 4.2.3 네이버 금융에서 주식티커 크롤링
(혼자한 연습)
목표: 네이버 금융에서 모든 상장기업 티커(6자리 ID) 긁어오기
이번 연습은 조금 어렵다. 해야 할 일이 여러 개다.
상당히 난해할 수 있으므로, 개별 작업을 하나하나 살펴본 후 마지막에 전부 합친다.
library(rvest)
library(httr)
library(tidyverse) #dplyr을 받아야 %>%(pipeline)을 사용할 수 있음
i <- 0 #i = 1: 코스닥
#일단 코스피부터, 나중에 loop 돌리면 되니까
url <- paste0('https://finance.naver.com/sise/',
'sise_market_sum.nhn?sosok=',i,'&page=1') #page=1: 첫페이지 (나중에 이 부분을 변수로 바꾸고,
#loop을 돌리면 모든 페이지 정보를 받음)
down_table <- GET(url)
down_table #charset=EUR-KR (인코딩)
## Response [https://finance.naver.com/sise/sise_market_sum.nhn?sosok=0&page=1]
## Date: 2019-08-10 16:41
## Status: 200
## Content-Type: text/html;charset=EUC-KR
## Size: 95.6 kB
##
##
##
##
##
##
##
## <!-- global include -->
##
##
## ...
navi.final =
read_html(down_table, encoding = 'EUC-KR') %>%
html_nodes(., '.pgRR') %>%
html_nodes(., 'a') %>%
html_attr(., 'href')
navi.final
## [1] "/sise/sise_market_sum.nhn?sosok=0&page=31"
navi.final 에서 마지막 두 자리가 곧 페이지 마지막 번호가 됨. 따라서 코스피의 경우 31임을 알 수 있음
navi.final <-
navi.final %>%
str_split(., "=") %>%
unlist() %>%
tail(., 1) %>%
as.numeric()
navi.final
## [1] 31
Sys.setlocale("LC_ALL", "English") #오류 방지를 위해 시스템 언어를 영어로 수정
table <-
read_html(down_table, encoding = "EUC-KR") %>% #전체 내용에서 일단 html을 읽어내야 함
html_table(fill = TRUE) #table 식 자료는 이 코드다 필요
table <- table[[2]] #list 형에서 이 부분이 바로 얻어오고자 하는 테이블임
Sys.setlocale("LC_ALL", "Korean") #다시 한국어로 변경
print(head(table))
## N 종목명 현재가 전일비 등락률 액면가 시가총액 상장주식수
## 1 NA
## 2 1 삼성전자 43,150 500 +1.17% 100 2,575,961 5,969,783
## 3 2 SK하이닉스 73,300 1,000 +1.38% 5,000 533,626 728,002
## 4 3 삼성전자우 35,500 100 +0.28% 100 292,125 822,887
## 5 4 현대차 132,500 2,500 +1.92% 5,000 283,110 213,668
## 6 5 NAVER 142,500 2,500 +1.79% 100 234,859 164,813
## 외국인비율 거래량 PER ROE 토론실
## 1 NA <NA> <NA> NA
## 2 57.61 9,076,689 7.16 19.63 NA
## 3 51.51 2,058,467 3.43 38.53 NA
## 4 92.95 717,379 5.89 N/A NA
## 5 44.31 512,312 24.76 2.20 NA
## 6 59.14 367,996 36.20 12.97 NA
table[, ncol(table)] = NULL #마지막 열은 필요 없으므로 날려버리자 (토론실)
table <- na.omit(table) #자료가 없는 행은 날려버리자(Missing value 문제가 아니고, 컴퓨터 코드 상 자료가 없는 부분이 이렇게 처리 돼 있음)
table %>% head()
## N 종목명 현재가 전일비 등락률 액면가 시가총액 상장주식수
## 2 1 삼성전자 43,150 500 +1.17% 100 2,575,961 5,969,783
## 3 2 SK하이닉스 73,300 1,000 +1.38% 5,000 533,626 728,002
## 4 3 삼성전자우 35,500 100 +0.28% 100 292,125 822,887
## 5 4 현대차 132,500 2,500 +1.92% 5,000 283,110 213,668
## 6 5 NAVER 142,500 2,500 +1.79% 100 234,859 164,813
## 10 6 현대모비스 243,500 7,000 +2.96% 5,000 232,072 95,307
## 외국인비율 거래량 PER ROE
## 2 57.61 9,076,689 7.16 19.63
## 3 51.51 2,058,467 3.43 38.53
## 4 92.95 717,379 5.89 N/A
## 5 44.31 512,312 24.76 2.20
## 6 59.14 367,996 36.20 12.97
## 10 49.09 190,639 12.55 6.30
share_id <-
read_html(down_table, encoding = "EUC-KR") %>%
html_nodes(., 'tbody') %>%
html_nodes(., 'td') %>%
html_nodes(., 'a') %>%
html_attr(., 'href')
share_id %>% head()
## [1] "/item/main.nhn?code=005930" "/item/board.nhn?code=005930"
## [3] "/item/main.nhn?code=000660" "/item/board.nhn?code=000660"
## [5] "/item/main.nhn?code=005935" "/item/board.nhn?code=005935"
share_id <-
sapply(share_id, function(x) {
substr(x, nchar(x) - 5, nchar(x))
})
share_id <- unique(share_id)
share_id %>% head(10)
## [1] "005930" "000660" "005935" "005380" "035420" "012330" "051910"
## [8] "068270" "017670" "055550"
table$N <- share_id
colnames(table)[1] = '종목코드'
rownames(table) = NULL
table %>% head()
## 종목코드 종목명 현재가 전일비 등락률 액면가 시가총액 상장주식수
## 1 005930 삼성전자 43,150 500 +1.17% 100 2,575,961 5,969,783
## 2 000660 SK하이닉스 73,300 1,000 +1.38% 5,000 533,626 728,002
## 3 005935 삼성전자우 35,500 100 +0.28% 100 292,125 822,887
## 4 005380 현대차 132,500 2,500 +1.92% 5,000 283,110 213,668
## 5 035420 NAVER 142,500 2,500 +1.79% 100 234,859 164,813
## 6 012330 현대모비스 243,500 7,000 +2.96% 5,000 232,072 95,307
## 외국인비율 거래량 PER ROE
## 1 57.61 9,076,689 7.16 19.63
## 2 51.51 2,058,467 3.43 38.53
## 3 92.95 717,379 5.89 N/A
## 4 44.31 512,312 24.76 2.20
## 5 59.14 367,996 36.20 12.97
## 6 49.09 190,639 12.55 6.30
data = list() #여기에 최종 결과가 담기게 될 것
# i = 0 은 코스피, i = 1 은 코스닥
for (i in 0:1) { #큰 loop (코스피 & 코스닥)
ticker = list() #첫번째는 코스피 페이지별 테이블이, 두 번째는 코스닥 페이지별 테이블이 담기게 될 것
url = #일단 모든 페이지 정보를 담아온다
paste0('https://finance.naver.com/sise/',
'sise_market_sum.nhn?sosok=',i,'&page=1')
down_table = GET(url)
# 최종 페이지 번호 찾아주기
navi.final = read_html(down_table, encoding = "EUC-KR") %>%
html_nodes(., ".pgRR") %>%
html_nodes(., "a") %>%
html_attr(.,"href") %>%
strsplit(., "=") %>%
unlist() %>%
tail(., 1) %>%
as.numeric()
# 첫번째 부터 마지막 페이지까지 for loop를 이용하여 테이블 추출하기
for (j in 1:navi.final) {
# 각 페이지에 해당하는 url 생성
url = paste0(
'https://finance.naver.com/sise/',
'sise_market_sum.nhn?sosok=',i,"&page=",j)
down_table = GET(url)
Sys.setlocale("LC_ALL", "English")
# 한글 오류 방지를 위해 영어로 로케일 언어 변경
table = read_html(down_table, encoding = "EUC-KR") %>%
html_table(fill = TRUE)
table = table[[2]] # 원하는 테이블 추출
Sys.setlocale("LC_ALL", "Korean")
# 한글을 읽기위해 로케일 언어 재변경
table[, ncol(table)] = NULL # 토론식 부분 삭제
table = na.omit(table) # 빈 행 삭제
# 6자리 티커만 추출
symbol = read_html(down_table, encoding = "EUC-KR") %>%
html_nodes(., "tbody") %>%
html_nodes(., "td") %>%
html_nodes(., "a") %>%
html_attr(., "href")
symbol = sapply(symbol, function(x) {
substr(x, nchar(x) - 5, nchar(x))
}) %>% unique()
# 테이블에 티커 넣어준 후, 테이블 정리
table$N = symbol
colnames(table)[1] = "종목코드"
rownames(table) = NULL
ticker[[j]] = table #페이지별 테이블을 ticker 리스트에 담아줌
Sys.sleep(0.5) # 페이지 당 0.5초의 슬립 적용
}
# do.call을 통해 리스트를 데이터 프레임으로 묶기
ticker = do.call(rbind, ticker) #ticker 리스트에는 개별 cart마다 코스닥 or 코스피 페이지별 테이블이 담겨 있음. 그것을 하나로 합치는 것임
data[[i + 1]] = ticker #첫째 cart에는 코스피 페이지별 테이블이 모두 합쳐진 data.frame이, 두 번째는 코스닥 자료가 들어감
}
# 코스피와 코스닥 테이블 묶기
data = do.call(rbind, data) #두 data.frame을 묶어줌
data %>% head()
## 종목코드 종목명 현재가 전일비 등락률 액면가 시가총액 상장주식수
## 1 005930 삼성전자 43,150 500 +1.17% 100 2,575,961 5,969,783
## 2 000660 SK하이닉스 73,300 1,000 +1.38% 5,000 533,626 728,002
## 3 005935 삼성전자우 35,500 100 +0.28% 100 292,125 822,887
## 4 005380 현대차 132,500 2,500 +1.92% 5,000 283,110 213,668
## 5 035420 NAVER 142,500 2,500 +1.79% 100 234,859 164,813
## 6 012330 현대모비스 243,500 7,000 +2.96% 5,000 232,072 95,307
## 외국인비율 거래량 PER ROE
## 1 57.61 9,076,689 7.16 19.63
## 2 51.51 2,058,467 3.43 38.53
## 3 92.95 717,379 5.89 N/A
## 4 44.31 512,312 24.76 2.20
## 5 59.14 367,996 36.20 12.97
## 6 49.09 190,639 12.55 6.30
data %>% tail()
## 종목코드 종목명 현재가 전일비 등락률 액면가 시가총액
## 2884 258790 케이비제11호스팩 2,225 15 -0.67% 100 71
## 2885 323210 이베스트이안스팩1호 2,150 5 -0.23% 100 69
## 2886 264290 한화에이스스팩3호 2,195 15 +0.69% 100 68
## 2887 021045 대호피앤씨우 1,320 0 0.00% 500 56
## 2888 032685 소프트센우 23,200 850 +3.80% 500 33
## 2889 149940 모다 155 0 0.00% 500 33
## 상장주식수 외국인비율 거래량 PER ROE
## 2884 3,210 0.00 5,005 370.83 0.33
## 2885 3,200 1.19 144,606 N/A N/A
## 2886 3,080 0.12 9,310 439.00 0.28
## 2887 4,242 0.07 12,283 47.14 N/A
## 2888 143 0.15 3,228 -1,288.89 N/A
## 2889 21,160 0.94 0 -0.32 -105.84