국토교통부 실거래가 데이터 크롤링 코드

국토교통부 실거래가 데이터 스크래핑 코드를 공유한다. 블로그에 썼던 데이터 분석에 사용한 데이터는 친분이 있는 분으로 부터 받은 데이터인데, 새로운 매매 데이터가 올라가면서 매번 요청하기 힘들것 같아서 코드를 작성해 봤고, 아래와 같이 간단하게 스크래핑 코드를 만들 수 있었다.

데이터 스크래핑 코드는 항상 그렇듯이 임시방편적이고, 코드가 깨끗하지 않다. 그래서 좀 색다르게 magrittr 방식으로 코딩해 봤으나 그다지 나아 보이지 않는다. ;;

수백만건의 데이터를 아래와 같은 간단한 코드로 수집할 수 있다는게 데이터 크롤링의 재미가 아닐까 생각하며, 다시한번 rvest, stringi, XLConnect, data.table과 같은 유용한 패키지의 존재에 감사한다.

library(rvest)
library(httr)
library(stringi)
library(XLConnect)
library(data.table)

## 엑셀 데이터 다운로딩 부분
# 데이터는 working dir아래 data 디렉토리에 쌓인다. 따리서 data 디렉토리를 만들어 주자!

su <- file("succ.txt", "w")

agent_nm <- 
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0"

maxidx <- html('http://rt.molit.go.kr/rtFile.do?cmd=list') %>% 
  html_nodes('.notiWhite1 .notiBorad01') %>%
  html_text %>% as.numeric %>% max

for(i in maxidx:1){
  urls_view <- sprintf("http://rt.molit.go.kr/rtFile.do?cmd=view&seqNo=%d", i)
  r <- GET(urls_view,
           user_agent(agent_nm))
  htxt <- html(r, "text")

  if((html_nodes(htxt, "td.notiBorad14")[[2]]  %>% 
        html_text()  %>% 
        stri_trim_both) == '첨부파일이 존재하지 않습니다.') next

  download_tags <- html_nodes(htxt, "td.notiBorad14")[[2]] %>%
    html_nodes('a[href^="javascript:jsDown"]')  

  for(dtag in download_tags){

    dtag %>% html_attr("href") %>% 
      stri_match_all_regex(pattern="javascript:jsDown\\('([0-9]+)','([0-9]+)'\\);") %>%
      .[[1]]  %>%  
          { 
            f_idx <<- .[2] %>% as.numeric
            s_idx <<- .[3] %>% as.numeric
          }

    f_nm <- dtag %>% html_text

    urls <- sprintf("http://rt.molit.go.kr/rtFile.do?cmd=fileDownload&seq_no=%d&file_seq_no=%d", f_idx,s_idx)
    r <- GET(urls,
             user_agent(agent_nm))
    bin <- content(r, "raw")

    #1kb 미만의 데이터는 버림(에러 페이지?) 
    if(length(bin) < 1000) next
    writeBin(bin, sprintf("data/%s",f_nm))
    cat(sprintf("%d, %d\n", f_idx,s_idx), file = su)
    print(sprintf("%d, %d", f_idx,s_idx))
  }
}

close(su)




## 엑셀 데이터에서 테이블을 추출해 하나의 아파트 매매 데이터로 통합하는 코드 
## 연립 다세대, 단독 다가 데이터도 간단한 코드 변환으로 통합할 수 있다. 


f_list <- list.files('data') %>%  
  stri_trans_nfc  %>% 
  .[stri_detect_fixed(.,'매매아파트')]

total_list <- list()

#파일의 각 시트(지역)를 data.table로 변환하고 필요 필드 추가함 
for(xlsf in f_list){
  wb <- loadWorkbook(paste0('data/',xlsf))
  sells <- list()
  fname <- stri_replace_last_fixed(xlsf, '.xls',"")
  yyyymm <- substring(fname, 1, 6)
  typenm <- substring(fname, 9)
  for(nm in getSheets(wb)) {
    df <- data.table(readWorksheet(wb, sheet = nm, header = TRUE))
    df[,`:=`(region=nm, yyyymm=yyyymm, typenm=typenm)]
    df[,`거래금액.만원.`:= stri_replace_all_fixed(`거래금액.만원.`, ',', '')]
    sells[[nm]] <- df
  }
  total_list[[paste0(yyyymm,typenm)]] <- rbindlist(sells)
}

result_sales_dt <- rbindlist(total_list)

#결과 데이터 저장 
save(result_sales_dt, file='result_sales_dt.RData')

실거래가 페이지가 바뀌지 않는 이상 동작을 할 것이고, result_sales_dt객체에 2015년 1월 기준 4,964,004건의 매매데이터가 쌓여 있는 것을 확인해 볼 수 있을 것이다.

사족이나 그동안 스크래핑은 Python과 같은 다른 언어를 사용하거나 webkit 라이브러리를 이용해 브라우저 객체를 통해 스크래핑 하곤 했는데, 이젠 여러 패키지 덕분에 R에서도 매우 간단해졌다. 10년 전만해도 HTTP 프로토콜 책을 옆에 끼고 크롤러 코딩을 했었는데, 격세지감을 느낄 따름이다.

윈도우에서 동작여부가 매우 궁금하나, 이런 부분에 대해서는 case by case라 시간 소모하고 싶지 않다.

그러나 참고를 위해서 코드가 동작하는 환경 정보는 추가한다.

## R version 3.1.2 (2014-10-31)
## Platform: x86_64-apple-darwin13.4.0 (64-bit)
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] RWordPress_0.2-3    knitr_1.9           XLConnect_0.2-10   
## [4] XLConnectJars_0.2-9 stringi_0.4-1       rvest_0.2.0        
## [7] data.table_1.9.4   
## 
## loaded via a namespace (and not attached):
##  [1] bitops_1.0-6    chron_2.3-45    digest_0.6.8    evaluate_0.5.5 
##  [5] formatR_1.0     htmltools_0.2.6 httr_0.6.1      magrittr_1.5   
##  [9] markdown_0.7.4  plyr_1.8.1      Rcpp_0.11.4     RCurl_1.95-4.5 
## [13] reshape2_1.4.1  rJava_0.9-6     rmarkdown_0.5.1 stringr_0.6.2  
## [17] tools_3.1.2     XML_3.98-1.1    XMLRPC_0.3-0    yaml_2.1.13

CC BY-NC 4.0 국토교통부 실거래가 데이터 크롤링 코드 by from __future__ import dream is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.