사이드 프로젝트를 하나 시작해보았는데요!
요즘 개인적으로 부동산 공부를 하고 있는데, 여간 여렵고 힘든 일이 아니다 ㅎㅎ.. 하지만, 사는 동안 떼어낼래야 뗄 수 없는 중요한 요소이기도 하고 부동산에 관심이 있었던지라 매우 뿌듯하고 보람차게 배우고 있다!
이러한 배경 하에 부동산 수업듣고, 부동산 시세를 탐색하는 과제가 생겼다. 서울에만 25개의 자치구와 426개의 행정동이 있고 약 150만 호의 아파트가 있다고 하는데.... 이 많은 것을 어떻게.. 조사하지 ??
조사 방법을 짧게 설명하면,
- 네이버 부동산 -> 아파트, 빌라 에 따른 매매, 전세 확인 -> 평형 별로 확인
- 이런 방식으로 아파트 평형당 매매가, 전세가를 확인하고, 손으로 엑셀을 정리하는 정성이 필요하다. 생각해보니 이건 지금 시점의 조사인거고 업데이트를 또 해줘야하는 구조이다.
- 감을 잡는 것이 중요하니, 우선 시작을 해보았다. 한 10개 쯤 조사했나 ? 벌써 막막하다. 심지어 현실을 알게되니 마음이 더 무거워져서 더 동기가 사라지는 기부니다.
- 이렇게 손가락을 멈춘 채 어떻게 하면 좀 더 효율적으로, 장기적으로 잘 분석할 수 있을지 고민하다가 오픈된 데이터가 있지 않을까 부동산 Open Api를 검색하니, 나와 같은 프로젝트를 했던 사람들이 몇년 전에 보였다. (이렇게 느려요... ㅋ)
그래도 나는 안해봤으니깐, 내가 원하는 방식은 조금 다르기 때문에 직접 나만의 프로젝트를 만들어보기로 하였다. 그리고 open api를 처음 써보기도 하고 오랜만에 R을 사용하여 진행하기 때문에, 과정을 기록하고 싶어 휴일에 짬내서 작업을 해보고 조금씩 끄적여본다.
이번 글은 국토교통부에서 제공하는 Open API에 직접 요청하고 원하는 데이터들을 불러오는 과정을 기록한다. 이번 프로젝트에서는 R를 사용할 예정이다.
✅ 데이터 소개
국토교통부에서는 부동산 실거래가 공개 시스템을 통해 아파트 매매 거래 정보를 Open API 형태로 제공한다. API를 요청할 때 필요한 요청 파라미터 중 법정동 코드가 있으며, 해당 자료는 다른 사이트에서 다운받을 수 있다.
- 국토교통부_아파트 매매 실거래가 상세 자료 : xml 자료
- 법정동 코드 자료 : 위 xml 자료를 사용하기 위해서 법정동코드가 필요한데, 이에 해당하는 메타 정보가 있다.
✅ 필요한 패키지 설치
# 필요한 패키지 설치 & 로드
library(httr)
library(jsonlite)
library(tidyverse)
✅ R 코드로 데이터 요청하기( 법정동코드 데이터, 매매 open api )
1) 법정동 코드 데이터
# 법정동 코드 데이터
library(data.table)
file_path <- "~/법정동코드 전체자료.txt"
data <- fread(file_path, encoding = "UTF-8")
# 컬럼명 영문 변경 & 현존하는 법정동 코드 확보
clean_date <- data %>%
rename(c(
"code" = `법정동코드`,
"name" = `법정동명`,
"is_exist" = `폐지여부`
)) %>%
filter(is_exist == "존재") %>%
mutate_at(c("code"), as.character)
# 주소 분리 및 법정동 코드 추출
code <- clean_date %>%
mutate(
split_name = str_split(name, " "), # 공백 기준으로 문자열 분리
city_name = map_chr(split_name, ~ ifelse(length(.x) >= 1, .x[1], NA)), # 시 이름 추출
gu_name = map_chr(split_name, ~ ifelse(length(.x) >= 2, .x[2], NA)), # 구 이름 추출
dong_name = map_chr(split_name, ~ ifelse(length(.x) >= 3, .x[3], NA)), # 동 이름 추출
gu_code = str_sub(code, 1, 5) # 법정동 코드 추출
) %>%
select(city_name, gu_name, dong_name, gu_code) %>%
distinct()
# 서울시 한정 법정동 코드 추출
seoul_gu_code <- code %>%
filter(grepl('서울', city_name)) %>%
select(gu_name, gu_code) %>%
distinct()
2) 매매 open api
- API 목록을 보면, 필요 파라미터를 확인할 수 있다. 필요한 파라미터의 값을 생성하고 데이터를 요청한다.
- 요청 파라미터 : 지역코드, 계약월, 인증키 (그 외는 필수값이라고 되어 있지만, 없어도 요청은 된다.)
# 조회하고 싶은 기간
year <- sprintf("%04d", 2021:2025) # "2015" ~ "2019"
month <- sprintf("%02d", 1:12) # "01" ~ "12"
base_date_list <- as.vector(outer(year, month, paste0)) # 모든 연도와 월 조합 생성
# API 요청 URL
url <- "https://apis.data.go.kr/1613000/RTMSDataSvcAptTradeDev/getRTMSDataSvcAptTradeDev"
service_key = "6Of2c4/W7poqNtorAWsMwHhYbtk0O5UDMGAMwfJyVFj0ZTlvbjyHjHiVNVTgutE3L7m2AxwAUodhw2mhGQz87g=="
# 📌 LAWD_CD와 DEAL_YMD를 쉼표로 구분된 문자열로 변환
lawd_cd_string <- paste(seoul_gu_code$gu_code, collapse = ",") # 서울 구 코드 문자열
deal_ymd_string <- paste(base_date_list, collapse = ",") # 날짜 문자열
# 요청 파라미터 설정 및 요청 URL 생성
query_params <- list(LAWD_CD = base_code,
DEAL_YMD = base_date,
serviceKey = service_key)
# (에러 수정을 위해 필요) user agent 임의 설정
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36"
# 📌 API 반복 호출
api_results <- request_combinations %>%
mutate(response = map2(LAWD_CD, DEAL_YMD, ~ {
query_params <- list(LAWD_CD = .x, # 개별 구 코드
DEAL_YMD = .y, # 개별 날짜
serviceKey = service_key)
# GET 요청 보내기
response <- GET(url, query = query_params, user_agent(ua))
# 응답 데이터 JSON 파싱
response_text <- content(response, "text", encoding = "UTF-8")
# JSON이 아닌 경우 (에러 응답일 경우) 처리
if (str_detect(response_text, "SERVICE_KEY_IS_NOT_REGISTERED_ERROR")) {
return(tibble(error = "Invalid API Key"))
} else if (str_detect(response_text, "<OpenAPI_ServiceResponse>")) {
return(tibble(error = "No Data Available"))
}
# JSON 파싱 시도, 실패하면 빈 tibble 반환
response_json <- tryCatch(
fromJSON(response_text, flatten = TRUE),
error = function(e) return(NULL)
)
# 응답 데이터에서 필요한 정보 추출
if (!is.null(response_json$response$body$items) && response_json$response$body$items != "") { # 데이터가 존재하는지 안전하게 확인
items <- response_json$response$body$items$item
df <- as_tibble(response_json$response$body$items$item) %>%
mutate(LAWD_CD = .x,
DEAL_YMD = .y) %>%
apply_schema() # ✅ 스키마 적용
return(df)
} else {
return(tibble(error = "Empty Response"))
}
}))
# 전체 데이터 통합
bind_rows(api_results$response)
- 요청이 성공하면 요청 결과의 response 코드가 200으로 확인된다.
- API를 반복 요청해서 받은 api_results 의 결과는 각 지역코드, 거래일자, 응답값(데이터)를 가진 데이터프레임으로 확인할 수 있다.
- 그럼 이제 응답값(데이터프레임)을 행으로 모두 연결하면 된다.
# 📌 API를 반복 요청하여 받은 데이터는 response 컬럼 안에 있던 데이터프레임으로 저장되어 있다.
# bind_rows()를 사용해서 모든 응답 데이터를 하나의 데이터프레임으로 합친다.
bind_rows(api_results$response) %>%
write.csv("~/전국부동산데이터")
✅ 에러 기록 ⚠️
- API를 처음 요청했을 때 200 코드는 떴으나 error 코드(04)도 함께 뜨면서, 데이터가 확인 안되는 상황이 발생했다. 요청된 주소를 창에서 확인했을 때는 제대로 요청된 것이 맞았으나 왜 데이터 확인이 안되는지 이해가 안갔다.
- 결론적인 이유는 user agent가 처음보는 값(?)을 가지고 있어서 에러가 발생했는데, 에러 코드로 보았을 때 정확하게 해당 원인인지 파악할 수가 없어서 요청된 파라미터를 하나하나 맞춰서 찾아보았다.
- 그 외 기술 문서에도 에러코드에 대한 상세 설명이 있으니, 확인할 수 있다.
직접 웹사이트에서 엑셀로 하나하나 수집하던 거래 내역을 API로 자동화하니 시간도 절약되고, 더 많은 데이터를 쉽게 다룰 수 있었다.
다음 글에서는 수집한 데이터를 분석하는 방법을 다루기로 하쟈 !
읽어주셔서 감사합니다 😊
'R' 카테고리의 다른 글
[오류] rJava로 인해 패키지가 로드 안되는 경우 (0) | 2022.10.19 |
---|
댓글