본문 바로가기
데이터분석/R

[R 데이터분석 with 샤이니] 자료 수집 : API 크롤러 만들기

by 버섯도리 2022. 6. 29.

> ## 03-1 크롤링 정비 : 무엇을 준비할까?

> # Step 1 : 작업 폴더 설정하기

> install.packages("rstudioapi")
> # 작업 폴더 설정
> setwd(dirname(rstudioapi::getSourceEditorContext()$path))
> getwd()
[1] "D:/1_Study/1_BigData/01_R/02_Doit_R_Shiny"

> # Step 2 : 수집 대상 지역 설정하기
>

> loc <- read.csv("./01_code/sigun_code/sigun_code.csv", fileEncoding = "UTF-8")
> loc$code <- as.character(loc$code)
> head(loc, 2)
   code       sido sigungu    addr_1            addr_2
1 11110 서울특별시  종로구 서울_종로 서울특별시 종로구
2 11140 서울특별시    중구 서울_중구   서울특별시 중구

> # Step 3 : 수집 기간 설정하기

> datalist <- seq(from = as.Date('2021-01-01'),
+                 to   = as.Date('2021-12-31'),
+                 by   = '1 month')
> datalist <- format(datalist, format='%Y%m')
> datalist[1:3]
[1] "202101" "202102" "202103"

> # Step 4 : 인증키 입력하기

> # 공공데이터포털(data.go.kr)에서 발급받은 인증키
> service_key <- "Y9OOOOOOOOOOOOOOOOOOOOOOOOOOO"

>

> ## 03-2 요청 목록 생성 : 자료를 어떻게 요청할까?

> # Step 1 : 요청 목록 만들기

> url_list <- list()
> cnt <- 0

> # Step 2 : 요청 목록 채우기

> for (i in 1:nrow(loc)) {
+   for (j in 1:length(datalist)) {
+     cnt <- cnt + 1
+     url_list[cnt] <- paste0("http://openapi.molit....DataSvcAptTrade?",
+                             "LAWD_CD=", loc[i,c("code")],
+                             "&DEAL_YMD=", datalist[j],
+                             "&serviceKey=", service_key,
+                             "&numOfRows=", 100)
+   }
+   Sys.sleep(0.1)
+   msg <- paste0("[", i, "/", nrow(loc), "]  ", loc[i,c("sigungu")], "의 크롤링 목록이 생성됨 => 총 [", cnt, "] 건")
+   cat(msg, "\n\n")
+ }
[1/25]  종로구의 크롤링 목록이 생성됨 => 총 [12] 건 

[2/25]  중구의 크롤링 목록이 생성됨 => 총 [24] 건 

...

[25/25]  강동구의 크롤링 목록이 생성됨 => 총 [300] 건 

> # Step 3 : 요청 목록 확인하기

> length(url_list)
[1] 300
> browseURL(url_list[[1]])


>

> ## 03-3 크롤러 제작 : 자동으로 자료 수집하기

> # Step 1 : 임시 저장 리스트 만들기

> library(XML)
> library(data.table)
> library(stringr)

> raw_data <- list()    # XML 임시 저장소
> root_Node <- list()   # 거래 내역 추출 임시 저장소
> total <- list()       # 거래 내역 정리 임시 저장소
> dir.create("02_raw_data")

> # Step 2 : 자료 요청하고 응답받기

> for (i in 1:length(url_list)) {
+   raw_data[[i]] <- xmlTreeParse(url_list[i], useInternalNodes = TRUE, encoding = "utf-8")
+   root_Node[[i]] <- xmlRoot(raw_data[[i]]) # xmlRoot로 루트 노드 이하 추출
+   
+   # Step 3 : 전체 거래 건수 확인하기
+   
+   items <- root_Node[[i]][[2]][['items']]   # 전체 거래 내역(items) 추출
+   size <- xmlSize(items)                    # 전체 거래 건수 확인

+   # Step 4 : 개별 거래 내역 추출하기
+   
+   item <- list()
+   item_temp_dt <- data.table()
+   Sys.sleep(.1)
+   
+   for (m in 1:size) {
+     #---# 세부 거래 내역 분리
+     item_temp <- xmlSApply(items[[m]], xmlValue)
+     item_temp_dt <- data.table(year = item_temp[4],      # 거래 연도
+                                month = item_temp[7],     # 거래 월
+                                day = item_temp[8],       # 거래 일
+                                price = item_temp[1],     # 거래 금액
+                                code = item_temp[12],     # 지역 코드
+                                dong_nm = item_temp[5],   # 법정동
+                                jibun = item_temp[11],    # 지번
+                                con_year = item_temp[3],  # 건축 연도
+                                apt_nm = item_temp[6],    # 아파트 이름
+                                area = item_temp[9],      # 전용 면적
+                                floor = item_temp[13]     # 층수
+                                )
+     item[[m]] <- item_temp_dt
+   }
+   
+   apt_bind <- rbindlist(item)
+   
+   # Step 5 : 응답 내용 저장하기
+   
+   region_nm <- subset(loc, code==str_sub(url_list[i],115,119))$addr_1
+   month <- str_sub(url_list[i],130,135) # YYYYMM
+   path <- as.character(paste0("./02_raw_data/", region_nm, "-", month, ".csv"))
+   write.csv(apt_bind, path)
+   msg <- paste0("[", i, "/", length(url_list), "] 수집한 데이터를 [", path, "]에 저장합니다.")
+   cat(msg, "\n\n")
+ }
[1/300] 수집한 데이터를 [./02_raw_data/서울_종로-202101.csv]에 저장합니다. 

[2/300] 수집한 데이터를 [./02_raw_data/서울_종로-202102.csv]에 저장합니다. 

...

[300/300] 수집한 데이터를 [./02_raw_data/서울_강동-202112.csv]에 저장합니다. 

>

> ## 03-4 자료 정리 : 자료 통합하기

> # Step 1 : CSV 파일 통합하기

> setwd(dirname(rstudioapi::getSourceEditorContext()$path))
> files <- dir("./02_raw_data")
> library(plyr)
> apt_price <- ldply(as.list(paste0("./02_raw_data/", files)), read.csv) # 결합
> tail(apt_price, 2)
       X year month day        price  code ...
43390 45 2021    12  20       75,500 11260  ...
43391 46 2021    12  23       42,400 11260  ...

> # Step 2 : 통합 데이터 저장하기

> dir.create("./03_integraed")
> save(apt_price, file = "./03_integraed/03_apt_price.rdata")
> write.csv(apt_price, "./03_integraed/03_apt_price.csv")

 

 

 

 

 

 

출처 : 김철민, ⌜공공데이터로 배우는 R 데이터분석 with 샤이니⌟, 이지스퍼블리싱, 2022