IT/python

[python] 우리동네 아파트 전세가율 조회 사이트 만들어보기

고잉킴 2023. 11. 27. 11:42

안녕하세요. 요즘 날씨가 참 쌀쌀하네요. 
이와중에 저희 집에도 냉기가 돕니다. 매물을 내놓은지는 어언 1년이 다 되어가는 듯 한데 아직도 찾는 이가 하나 없네요.
 
그래서... 우리 동네의 대장 아파트의 전세가율은 어떻게 될까 확인해보려고 web을 간단하게 만들어보았는데요.
많이 허접하지만 소개해드리겠습니다.
 
우선 아파트 매매가와 전세가를 받아와야겠죠.
이 정보는 공공데이터포털에서 제공되는 OPENAPI를 활용하면 됩니다.
 

1. https://www.data.go.kr 에 접속후 데이터 요청 

저는 통합검색에서 검색해 각각 오픈 API - XML 국토교통부_아파트 전월세 자료, 국토교통부_아파트매매 실거래 자료를 선택하여
'활용신청' 을 선택하였습니다.
간단하게 사유를 쓰면 자동 승인되고 해당 API를 호출은 승인 후 한 2~3시간은 걸렸던 것 같습니다.
 
마이페이지 > 데이터 활용 > Open API > 활용신청 현황을 들어가면 참고문서에 기술문서.hwp (으휴.. 언제까지 hwp..)가 있습니다.
이를 참고해서 작성하면 되는데요.
 

2. Python 패키지 설치

실제 API호출은 request package를 사용하면 됩니다.

pip install streamlit ## frontend
pip install matplotlib ## chart

 

3. 구코드 확인하기

다양한 방법이 있겠지만 저는 https://www.code.go.kr/stdcode/regCodeL.do 여기서 법정동코드를 확인하였습니다.
구코드는 총 5자리로 서울시 동대문구는 11230 이네요. 종종 변경되는 것 같으니 수시로 확인하는 것이 좋을 것 같습니다.
 

4. 매매가 최근 3년치를 받아오기

저는 streamlit으로 web을 올렸는데요. 캐싱 기능을 위해 @st.cache_data를 넣었습니다. url에는 참고문서에 있던 서비스URL, serviceKey는 일반 인증키(Encoding) 부분을 사용하면 됩니다.

@st.cache_data
def get_maemae(url, serviceKey, gu_code, base_date):
    payload = "LAWD_CD=" + gu_code + "&" + "DEAL_YMD=" + base_date + "&" + "serviceKey=" + serviceKey
    res = requests.get(url + payload)
    data = json.loads(json.dumps(xmltodict.parse(res.text)))
    return data

 
문서에서 보시면 조회시 특정 년도 특정 월만 조회할 수 있게 되어 있습니다.
저는 월별로 데이터를 받아오기 위해 현재 날짜를 구해서 2021년부터 2023년 이번 달까지를 배열로 만들고 for문을 돌리는 방식으로 짰는데 혹시 더 좋은 방법이 있다면 알려주세요~

# 3년치 년월 배열 생성
def get_monthly_data_for_last_three_years():
    results = []
    current_year = datetime.now().year
    current_month = datetime.now().month

    for year in range(current_year - 2, current_year + 1):
        for month in range(1, 13):
            if year == current_year and month > current_month:
                break
            month_str = f"{year}{month:02d}"
            results.append(month_str)

    return results

results_date = get_monthly_data_for_last_three_years()

# 받아온 result가 xml이므로 해당 xml에서 body > items > item 태그 안의 내용을 추출
def get_items(response):
    df = response['response']['body']['items']['item'] 
    return df 

mitems_list = []

# 실제 매매 API 호출
for base_date in results_date:
    mres = get_maemae(mUrl, mKey, gu_code, base_date)  
    mitems_list += get_items(mres)

mdf = pd.DataFrame(mitems_list)

 

4. 전세가를 받아오기

전세가와 매매가 API 스펙을 보면 request param은 동일하더라구요. 그래서 url 정보만 변경해주면 됩니다. service key의 경우도 API별로 할당되는 것이 아니라 개인별로 할당되더라구요.

@st.cache_data
def get_jeonsay(url, serviceKey, gu_code, base_date):
    payload = "LAWD_CD=" + gu_code + "&" + "DEAL_YMD=" + base_date + "&" + "serviceKey=" + serviceKey
    res = requests.get(url + payload)
    data = json.loads(json.dumps(xmltodict.parse(res.text)))
    return data

 

5. 데이터 프레임 합치기

각 아파트, 전용면적, 년월 정보를 바탕으로 merge해서 계산을 해줍니다.

jdf = jdf[jdf['월세금액'] == "0"] ## 월세는 제외하고 전세만 필터
merged_df = pd.merge(mdf, jdf, on=['아파트', '전용면적', '년', '월'])
merged_df['거래금액'] = pd.to_numeric(merged_df['거래금액'].str.replace(',',''))
merged_df['보증금액'] = pd.to_numeric(merged_df['보증금액'].str.replace(',',''))
merged_df['전세가율'] = (merged_df['보증금액'] / merged_df['거래금액']) * 100

merged_df = merged_df[['아파트', '전용면적', '전세가율', '년', '월']]

merged_df['년월'] = merged_df['년'] + merged_df['월']

st.dataframe(merged_df)

 

6. 년월을 date type으로 변환

# Convert '년월' to datetime
merged_df['년월'] = pd.to_datetime(merged_df['년월'], format='%Y%m')

 

7. 아파트, 전용면적별로 차트 생성 ( 각 group은 tab으로 분리)

streamlit 에는 tab을 쉽게 구분할 수 있게끔 element로 제공이 되는데요. 이 기능을 활용해서 아파트/전용면적 별로 차트를 조회할 수 있게 해보겠습니다.

grouped = merged_df.groupby(['아파트', '전용면적'])

plt.rcParams['font.family'] = 'NanumBarunGothic'
plt.rcParams['font.sans-serif'] = ['NanumBarunGothic'] + plt.rcParams['font.sans-serif']
plt.rcParams['axes.unicode_minus'] = False

tab_names = [f"{apartment} - {area}" for apartment, area in grouped.groups.keys()]
tabs = st.tabs(tab_names)

for (apartment, area), group in grouped:

    with tabs[tab_names.index(apartment + " - " + area)]:
        monthly_avg = group.groupby('년월')['전세가율'].mean().reset_index()

        fig, ax = plt.subplots(figsize=(10, 6))
        ax.plot(monthly_avg['년월'], monthly_avg['전세가율'], marker='o')
        ax.set_title(f'Time Series of Jeonse Price Ratio')
        ax.set_xlabel('Yearmonth')
        ax.set_ylabel('Jeonse Price Ratio')
        ax.grid(True)
        ax.set_ylim(0, 100)
        plt.xticks(rotation=45)
        plt.tight_layout()

        st.pyplot(fig)

 
 

8. 결과

이런식으로 조회가 가능합니다. 조금 허접하지만 차트를 보니 점점 전세가율은 올라가고 있네요. 

streamlit chart

 
읽어주셔서 감사합니다.