국토부 실거래가 불러오기 파이썬코드

국토부 실거래가 불러오기 파이썬코드

원하는 지역의 실거래가를 일일이 확인해야 하였는데 아래 코드로 원하는 지역을 입력하여 새로운 국토부 실거래가 자료가 있으면 코드 실행일에 카카오톡으로 바로 알려주게 만들어 봤습니다.
그 중 국토부 실거래가만 불러와서 엑셀파일로 저장하는 파이썬 코드입니다.
코드에 대해선 하나도 모르니 챗gpt랑 엄청 싸워서 만들었습니다. ^^

이 코드는 국토교통부 API를 이용하여 특정 기간(입력한 년월 ~ 년월)의 아파트 실거래가 데이터를 수집하고,

이를 엑셀 파일로 저장하는 프로그램입니다.

코드 주요 기능

1. 사용자 입력을 통해 데이터 조회 기간 설정

  • 시작 연도와 월 (start_year, start_month)
  • 종료 연도와 월 (end_year, end_month)
  • 입력한 기간 동안의 모든 “년월” 리스트를 생성

2. 국토부 실거래가 API 호출 (molit_public_api 함수)

  • API 요청을 보내서 특정 지역의 실거래가 데이터를 가져옴
  • 데이터를 JSON 형태로 변환 후 pandas 데이터프레임으로 저장

3. 데이터 정리 및 가공

  • 필요한 컬럼만 선택 (아파트명, 층수, 거래금액 등)
  • 날짜(거래일, 거래월)를 숫자로 변환하고 두 자리 형식 유지
  • 데이터 정렬 (아파트명 오름차순, 거래월·거래일 내림차순)

4. 엑셀 파일로 저장

  • 수집된 데이터를 엑셀 파일(.xlsx)로 저장
  • 파일 이름: 아파트_실거래데이터_YYYYMM_YYYYMM.xlsx

5. 엑셀 파일 서식 적용

  • 테두리 추가
  • 글꼴(맑은 고딕) 적용
  • 가운데 정렬
  • 셀 너비 자동 조정

6. 최종 저장 및 완료 메시지 출력

코드 세부 분석

1. 국토부 API 요청 함수 (molit_public_api)

def molit_public_api(key, rcode, dealdate):
  • key: 국토부 API 서비스 키

  • rcode: 지역 코드 (법정동 코드)

  • dealdate: 조회할 년월 (예: '202403' → 2024년 3월)

 

API 요청 URL 생성

base = “http://apis.data.go.kr/1613000/RTMSDataSvcAptTrade/getRTMSDataSvcAptTrade?”
parameters = “serviceKey=%s&” % (key) + urlencode({
quote_plus(‘LAWD_CD’): rcode,
quote_plus(‘DEAL_YMD’): str(dealdate),
quote_plus(‘numOfRows’): str(9999)}, encoding=’UTF-8′)
  • LAWD_CD: 지역 코드 입력
  • DEAL_YMD: 조회할 년월 입력
  • numOfRows=9999: 한 번에 최대 9999건 가져오기

API 응답 처리

response = urlopen(Request(url))
rescode = response.getcode()
if rescode == 200:
response_body = response.read().decode(‘utf-8’)
else:
print(‘Error code: ‘ + str(rescode))
return None
  • 응답 코드가 200이면 데이터를 읽어서 처리
  • XML 형식의 데이터를 JSON으로 변환
  • 데이터가 있으면 pandas 데이터프레임으로 반환

 

2. 사용자 입력을 받아 기간 리스트 생성

start_year = input(“시작 연도를 입력하세요 (예: 2024): “)
start_month = input(“시작 월을 입력하세요 (예: 02): “)
end_year = input(“종료 연도를 입력하세요 (예: 2024): “)
end_month = input(“종료 월을 입력하세요 (예: 10): “)
  • 사용자가 시작/종료 연도 및 월 입력

 

입력한 기간 동안의 “년월” 리스트 생성

def get_yearmonth_list(start_year, start_month, end_year, end_month):
init_yearmonth = datetime.strptime(f”{start_year}{start_month}”, “%Y%m”).date()
end_yearmonth = datetime.strptime(f”{end_year}{end_month}”, “%Y%m”).date()
year_months = []

while init_yearmonth <= end_yearmonth:
year_months.append(init_yearmonth)
init_yearmonth += relativedelta(months=1)

return year_months

  • 입력한 시작 년월부터 종료 년월까지 한 달 단위로 리스트 생성
  • relativedelta(months=1): 한 달씩 증가

 

3. 기간별 API 호출 및 데이터 수집

final_df = pd.DataFrame()
for year_month in year_months:
try:
yearmonth = year_month.strftime(“%Y%m”)
df_molit_api = molit_public_api(molit_serviceKey, rcode=’지역코드입력’, dealdate=yearmonth)

if df_molit_api is not None:
selected_columns = [‘umdNm’, ‘aptNm’, ‘aptDong’, ‘floor’, ‘excluUseAr’, ‘dealYear’, ‘dealMonth’, ‘dealDay’, ‘dealAmount’, ‘dealingGbn’, ‘rgstDate’]
df_selected = df_molit_api[selected_columns]
final_df = pd.concat([final_df, df_selected], ignore_index=True)
print(f”{yearmonth} 데이터가 수집되었습니다.”)
else:
print(f”{yearmonth}: 조회 가능한 데이터가 없어 수집할 수 없습니다.”)
except Exception as e:
print(f”에러 발생: {str(e)}”)

  • year_month에 대해 API를 호출
  • 데이터를 final_df에 계속 추가

 

4. 데이터 정리 및 가공

final_df.columns = [‘읍면동명’, ‘아파트명’, ‘동’, ‘층수’, ‘전용면적’,’거래년도’, ‘거래월’, ‘거래일’, ‘거래금액’,’거래구분’, ‘등록일’]
  • 한글 컬럼명으로 변경

 

거래월, 거래일을 두 자리 숫자로 변환

final_df[‘거래월’] = pd.to_numeric(final_df[‘거래월’], errors=’coerce’)
final_df[‘거래월’] = final_df[‘거래월’].apply(lambda x: f'{int(x):02}’ if x < 10 else str(int(x)))

final_df[‘거래일’] = pd.to_numeric(final_df[‘거래일’], errors=’coerce’)
final_df[‘거래일’] = final_df[‘거래일’].apply(lambda y: f'{int(y):02}’ if y < 10 else str(int(y)))

데이터 정렬

final_df = final_df.sort_values(by=[‘아파트명’, ‘거래월’, ‘거래일’], ascending=[True, False, False])
  • 아파트명: 오름차순
  • 거래월, 거래일: 내림차순

 

5. 엑셀 파일 저장

final_filename = os.path.join(dirname, f’아파트_실거래데이터_{start_year}{start_month}_{end_year}{end_month}.xlsx’)
final_df.to_excel(final_filename, index=False, engine=’openpyxl’)
  • .xlsx 파일로 저장

 

엑셀 서식 적용

for row in ws.iter_rows(min_row=1, max_row=ws.max_row):
for cell in row:
cell.border = border
cell.font = font
cell.alignment = alignment
  • 테두리, 글꼴, 정렬 적용
  • 셀 크기 조정

아래는 전체코드입니다.

# 아파트실거래가 입력한 년월 ~ 년월 까지 불러오는 코드

from urllib.request import Request, urlopen

from urllib.parse import urlencode, quote_plus

from datetime import datetime

from dateutil.relativedelta import relativedelta

import openpyxl

import os

import json

import xmltodict

import pandas as pd

from openpyxl.styles import Border, Side, Font, Alignment

# 서비스키 설정 (발급받은 서비스키 입력)

molit_serviceKey = ‘발급받은 서비스키 입력’

# 국토부 API 호출 함수

def molit_public_api(key, rcode, dealdate):

try:

base = “http://apis.data.go.kr/1613000/RTMSDataSvcAptTrade/getRTMSDataSvcAptTrade?”

parameters = “serviceKey=%s&” % (key) + urlencode({

quote_plus(‘LAWD_CD’): rcode,

quote_plus(‘DEAL_YMD’): str(dealdate),

quote_plus(‘numOfRows’): str(9999)}, encoding=’UTF-8′)

 

url = base + parameters

request = Request(url)

response = urlopen(request)

rescode = response.getcode()

if rescode == 200:

response_body = response.read().decode(‘utf-8’)

else:

print(‘Error code: ‘ + str(rescode))

return None

jsonData = json.loads(json.dumps(xmltodict.parse(response_body)))

 

if jsonData[‘response’][‘body’][‘items’] is not None:

df = pd.DataFrame(jsonData[‘response’][‘body’][‘items’][‘item’])

return df

else:

return None

except Exception as e:

print(‘Exception occurred:’, str(e))

return None

# 연도와 월 리스트를 생성하는 함수

def get_yearmonth_list(start_year, start_month, end_year, end_month):

init_yearmonth = datetime.strptime(f”{start_year}{start_month}”, “%Y%m”).date()

end_yearmonth = datetime.strptime(f”{end_year}{end_month}”, “%Y%m”).date()

year_months = []

 

while init_yearmonth <= end_yearmonth:

year_months.append(init_yearmonth)

init_yearmonth += relativedelta(months=1)

 

return year_months

# 사용자로부터 시작 연도와 종료 연도 입력 받기

start_year = input(“시작 연도를 입력하세요 (예: 2024): “)

start_month = input(“시작 월을 입력하세요 (예: 02): “)

end_year = input(“종료 연도를 입력하세요 (예: 2024): “)

end_month = input(“종료 월을 입력하세요 (예: 10): “)

# 연도와 월 리스트 생성

year_months = get_yearmonth_list(start_year, start_month, end_year, end_month)

# 현재 작업 디렉토리 경로 설정

dirname = os.getcwd()  # 현재 작업 디렉토리 가져오기

# 최종 데이터프레임 초기화

final_df = pd.DataFrame()

# 각 월에 대한 데이터 수집

for year_month in year_months:

try:

yearmonth = year_month.strftime(“%Y%m”)

 

# API를 호출하여 데이터를 가져옴

df_molit_api = molit_public_api(molit_serviceKey, rcode=’지역코드입력’, dealdate=yearmonth)  #지역변경

 

# 데이터가 존재하면 최종 데이터프레임에 추가

if df_molit_api is not None:

# 원하는 컬럼만 선택

selected_columns = [‘umdNm’, ‘aptNm’, ‘aptDong’, ‘floor’, ‘excluUseAr’, ‘dealYear’, ‘dealMonth’, ‘dealDay’, ‘dealAmount’, ‘dealingGbn’, ‘rgstDate’ ]

df_selected = df_molit_api[selected_columns]

final_df = pd.concat([final_df, df_selected], ignore_index=True)

print(f”{yearmonth} 데이터가 수집되었습니다.”)

else:

print(f”{yearmonth}: 조회 가능한 데이터가 없어 수집할 수 없습니다.”)

except Exception as e:

print(f”에러 발생: {str(e)}”)

# 한글 컬럼 이름으로 변경

if not final_df.empty:

final_df.columns = [‘읍면동명’, ‘아파트명’, ‘동’, ‘층수’, ‘전용면적’,’거래년도’, ‘거래월’,  ‘거래일’, ‘거래금액’,’거래구분’, ‘등록일’ ]

 

# 거래월이 숫자가 아닌 경우 숫자로 변환

final_df[‘거래월’] = pd.to_numeric(final_df[‘거래월’], errors=’coerce’)

# 거래월을 한 자리 숫자일 경우 앞에 0을 붙이고, 두 자리 숫자는 그대로 유지

final_df[‘거래월’] = final_df[‘거래월’].apply(lambda x: f'{int(x):02}’ if x < 10 else str(int(x)))

# 거래일을 정수형으로 변환하고, 한 자리 숫자일 경우 앞에 0을 붙임

final_df[‘거래일’] = pd.to_numeric(final_df[‘거래일’], errors=’coerce’)  # 거래일을 숫자로 변환

final_df[‘거래일’] = final_df[‘거래일’].apply(lambda y: f'{int(y):02}’ if y < 10 else str(int(y)))

# 아파트명 내림차순, 거래월 내림차순 정렬

final_df = final_df.sort_values(by=[‘아파트명’, ‘거래월’, ‘거래일’], ascending=[True, False, False])

# 엑셀 파일 이름에 시작 년월과 마지막 년월 포함

final_filename = os.path.join(

dirname,

f’국토부_아파트_데이터_{start_year}{start_month}_{end_year}{end_month}.xlsx’

)  # 엑셀 파일 이름 설정

# 최종 데이터를 하나의 엑셀 파일로 저장

if not final_df.empty:

final_filename = os.path.join(dirname, f’아파트_실거래데이터_{start_year}{start_month}_{end_year}{end_month}.xlsx’)  # 엑셀 파일 이름 설정

final_df.to_excel(final_filename, index=False, engine=’openpyxl’)  # 엑셀로 저장

# 저장한 엑셀 파일 열기

wb = openpyxl.load_workbook(final_filename)

ws = wb.active

# 테두리 스타일 설정

thin = Side(style=’thin’)

border = Border(left=thin, right=thin, top=thin, bottom=thin)

# 글꼴 설정 (고딕체)

font = Font(name=’맑은 고딕’, size=11)  # ‘Malgun Gothic’이 일반적인 고딕체입니다.

# 정렬 설정 (가운데 정렬)

alignment = Alignment(horizontal=’center’)

# 테두리 및 셀 크기 조정

for row in ws.iter_rows(min_row=1, max_row=ws.max_row):

for cell in row:

cell.border = border  # 테두리 적용

cell.font = font  # 글꼴 적용

cell.alignment = alignment  # 가운데 정렬 적용

 

# 셀의 크기를 글자 수에 맞춰 수동으로 조정

if cell.value:

max_length = max(len(str(cell.value)), 10)  # 최소 너비를 10으로 설정

ws.column_dimensions[cell.column_letter].width = max_length

# 아파트명 열 너비 조정

apt_nm_col_letter = ‘B’  # ‘aptNm’이 두 번째 열이라고 가정

max_length_apt_nm = max(final_df[‘아파트명’].apply(lambda x: len(str(x))))  # 아파트명 최대 길이 계산

ws.column_dimensions[apt_nm_col_letter].width = max_length_apt_nm + 20  # 여유 공간 추가

# 변경된 내용 저장

wb.save(final_filename)

print(f”모든 데이터가 {final_filename}에 저장되었습니다.”)