파이썬(python) + 오픈 API(open api) 를 이용한 아파트 매매 실거래 가격 가져오기

Language/파이썬|2021. 7. 27. 20:12

파이썬(python) + 오픈 API(open api) 를 이용한 아파트 매매 실거래 가격 가져오기

공공데이터 open api 이용하기

공공데이터 포털 https://www.data.go.kr/ 라는 곳이 있습니다. 공공기관이 생성 또는 취득하여 관리하고 있는 공공데이터를 한 곳에서 제공하는 통합 창구 이며 국민이 쉽고편리하게 공공데이터를 이용할 수 있도록 파일데이터, 오픈API, 시각화 등 다양한 방식으로 제공하고 있으며, 누구라도 쉽고 편리한 검색을통해 원하는 공공데이터를 빠르고 정확하게 찾을 수 있는 곳입니다.

제가 오늘 이용하고자 하는 부동산 실거래 가격도 이곳에 등록되어 있습니다.

  • 공공데이터를 제공해주는 https://www.data.go.kr/ 접속합니다.
  • 회원 가입을 진행합니다.
  • 데이터 찾기에서 “아파트매매 실거래자료” 라고 입력하고 검색 아이콘을 클릭합니다.

  • 검색 결과에서 아래 내용을 선택합니다.

  • 해당 자료를 클릭하면 아래와 같은 정보를 확인할수 있습니다. 활용사례 탭을 클릭해보니 호갱노노 에서도 사용하고 있습니다. 제가 원하는 부동산 실거래 가격 이 맞네요 [활용신청] 버튼을 클릭하여 Api 신청을 진행합니다.

Api 신청이 완료되면 아래와 같이 마이페이지에에서 api 승인결과를 알수 있습니다

  • 아파트 매매 신고정보 조회 기술문서.hwp 파일을 열어서 api 사용하는 방법에 대해서 확인해 보겠습니다.

  • 상세기능 설명부분을 보시면 행정 표준코드 관리시스템 의 법정동 5자리와 계약년월 정보를 넘겨 데이터를 받는 구조입니다.

아래는 요청 메시지 명세서 입니다

  • 아래는 응답 메시지 명세서 입니다.

 

실제 데이터 가져오는 코드 작성

실제로 데이터를 가져오는 코드를 작성해보겠습니다.

import webbrowser

def getRTMSDataSvcAptTrade(LAWD_CD,DEAL_YMD,serviceKey): 
    url="http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade" 
    url=url+"?&LAWD_CD="+LAWD_CD
    url=url+"&DEAL_YMD="+DEAL_YMD
    url=url+"&serviceKey="+serviceKey
    webbrowser.open(url)
    return
    
getRTMSDataSvcAptTrade('11110','202001','일반 인증키를 입력해주세요')

위에 코드를 실행하면 아래와 같이 xml 데이터를 받을수 있습니다.

 

데이터 가공하기

가져온 데이터를 데이터 베이스화 하기 위해 BeautifulSoup,Pandas란 라이브러리를 사용하겠습니다. BeautifulSoup 은 HTML 및 XML 파일에서 원하는 데이터를 손쉽게 Parsing 할 수 있는 Python 라이브러리 이며 Pandas는 파이썬에서 사용하는 데이터분석 라이브러리로, 행과 열로 이루어진 데이터 객체를 만들어 다룰 수 있게 되며 보다 안정적으로 대용량의 데이터들을 처리하는데 매우 편리한 도구 입니다.

2개의 Python를 이용하여 xml을 파싱하고 데이터를 분석해보겠습니다.

아래 코드를 작성해 주세요.. 인증코드 부분은 자신이 받은 인증키를 넣어주세요.

 

from bs4 import BeautifulSoup
import pandas as pd
import urllib.request

req = urllib.request

def getRTMSDataSvcAptTrade(LAWD_CD,DEAL_YMD,serviceKey): 
    url="http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade" 
    url=url+"?&LAWD_CD="+LAWD_CD
    url=url+"&DEAL_YMD="+DEAL_YMD
    url=url+"&serviceKey="+serviceKey
    
    xml = req.urlopen(url)
    result = xml.read()
    soup = BeautifulSoup(result, 'lxml-xml')    
    
    items = soup.findAll("item")
    aptTrade = pd.DataFrame()
    
    for item in items:
        dealAmount          = item.find("거래금액").text
        buildYear           = item.find("건축년도").text
        dealYear            = item.find("년").text
        dong                = item.find("법정동").text
        apartmentName       = item.find("아파트").text
        dealMonth           = item.find("월").text
        dealDay             = item.find("일").text
        areaForExclusiveUse = item.find("전용면적").text
        jibun               = item.find("지번").text
        regionalCode        = item.find("지역코드").text
        floor               = item.find("층").text
        buildYear           = item.find("건축년도").text
        
        temp = pd.DataFrame(([[dealAmount,buildYear,dealYear,dong,apartmentName,dealMonth,dealDay,areaForExclusiveUse,jibun,regionalCode,floor,buildYear]]), columns=["dealAmount","buildYear","dealYear","dong","apartmentName","dealMonth","dealDay","areaForExclusiveUse","jibun","regionalCode","floor","buildYear"]) 
        aptTrade=pd.concat([aptTrade,temp])
    
    aptTrade=aptTrade.reset_index(drop=True)
    return aptTrade

getRTMSDataSvcAptTrade('11140','202006','인증코드')

실행결과는 아래와 같습니다. 원하는 데이터를 잘 가져왔습니다.

법정동 코드 데이터베이스화 하기

api에서 인자로 넘겨줘야 될 법정코드(LAWD_CD)이 값을 알아야 되는데요.. 이값은 api설명문서에 있는 http://code.go.kr 을 통해서 데이터를 확보하겠습니다. 해당 사이트에 접속한후 자주 이용하는 코드 부분의 2번항목 법정동 메뉴를 클릭합니다.

법정동코드 전체 다운로드 버튼을 클릭하세요

다운로드 파일을 열어보면 아래와 같은 문자열로 구성되어 있습니다.

법정동코드	법정동명	폐지여부
1100000000	서울특별시	존재
1111000000	서울특별시 종로구	존재
1111010100	서울특별시 종로구 청운동	존재
...

1~3 번째 row까지 지우고 아래와 같은 형태로 변경합니다. 이렇게 변경하는 이유는 텍스트파일을 읽어서 Pandas dataframe형태로 변경한후 sqllite에 손쉽게 데이터를 넣기 위함입니다.

dong_cd	do	si	my	ri	exyn
1111010100	서울특별시 종로구 청운동	존재
1111010200	서울특별시 종로구 신교동	존재
1111010300	서울특별시 종로구 궁정동	존재
1111010400	서울특별시 종로구 효자동	존재
1111010500	서울특별시 종로구 창성동	존재
1111010600	서울특별시 종로구 통의동	존재
1111010700	서울특별시 종로구 적선동	존재
1111010800	서울특별시 종로구 통인동	존재

파일명을 cd.txt로 바꾸고 쥬피터 노트북에서 python코드 작성중인 곳에 적당한 폴더에 위치합니다.

아래 파이썬 코드를 실행하면 conn.db에 dong이란 테이블이 만들어 집니다.

import pandas as pd
import sqlite3

con  = sqlite3.connect("files/conn.db")
df = pd.read_csv('files/cd.txt', sep = "\t", engine='python', encoding = "cp949")
df.to_sql('dong',con,schema=None,if_exists='replace',index=None,index_label=None, chunksize=None, dtype=None)
con.close()

sqlite db viewer로 테이블이 구조와 데이터를 확인합니다.

부동산 실거래 db 구축하기

아래와 같은 순서대로 코딩하겠습니다. 부동산 실거래 데이터가 언제부터 존재하는지 확인한 결과 2006년1월부터 데이터가 존재 했습니다. for문 사용해서 2006년 01월부터 2020년 07월 현재까지 모든 데이터를 가져오고 싶었지만 데이터량이 너무 많아서 데이터 베이스 구축할때 타임아웃이 발생하여 1년씩 데이터 베이스를 생성하겠습니다. 1년생성하고 또 1년생성하고 총 15번 정도 아래 코드를 실행하겠습니다. 아래 코드중 아래 4가지 변수값을 수정해서 데이터를 생성하시기 바랍니다.

sYear  = 2011
eYear  = 2011
sMonth = 1
eMonth = 12

코드 간단설명

  1. 법정동 정보 5자리를 distinct 해서 가져옵니다.
  2. 가져오고자 하는 년도를 입력합니다.
  3. 1~12월까지 데이터를 가져오도록 코드를 작성합니다.
import sqlite3
from bs4 import BeautifulSoup
import pandas as pd
import urllib.request

req = urllib.request

def getRTMSDataSvcAptTrade(LAWD_CD,DEAL_YMD,serviceKey): 
    url="http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade" 
    url=url+"?&LAWD_CD="+LAWD_CD
    url=url+"&DEAL_YMD="+DEAL_YMD
    url=url+"&serviceKey="+serviceKey
    
    xml = req.urlopen(url)
    result = xml.read()
    soup = BeautifulSoup(result, 'lxml-xml')    
    
    items = soup.findAll("item")
    aptTrade = pd.DataFrame()
    
    for item in items:
        dealAmount          = item.find("거래금액").text        
        dealYear            = item.find("년").text
        dong                = item.find("법정동").text
        apartmentName       = item.find("아파트").text
        dealMonth           = item.find("월").text
        dealDay             = item.find("일").text
        areaForExclusiveUse = item.find("전용면적").text
        regionalCode        = item.find("지역코드").text
        floor               = item.find("층").text
        
        try:
            jibun = item.find("지번").text
        except:
            jibun = ""
        
        try:
            buildYear = item.find("건축년도").text
        except:
            buildYear = ""
        
        temp = pd.DataFrame(([[dealAmount,buildYear,dealYear,dong,apartmentName,dealMonth,dealDay,areaForExclusiveUse,jibun,regionalCode,floor]]), columns=["dealAmount","buildYear","dealYear","dong","apartmentName","dealMonth","dealDay","areaForExclusiveUse","jibun","regionalCode","floor"]) 
            
        
        aptTrade=pd.concat([aptTrade,temp])
    
    aptTrade=aptTrade.reset_index(drop=True)
    return aptTrade


con  = sqlite3.connect("files/conn.db")
cursor = con.cursor()

sYear  = 2011
eYear  = 2011
sMonth = 1
eMonth = 12

rows = cursor.execute('''select distinct substr(dong_cd,0,6) from dong ''')
silTrade = pd.DataFrame()

for row in rows:    
    if row[0][2:3] != '0':
        for i in range(sYear, eYear+1, 1):
            for j in range(sMonth, eMonth+1, 1):
                yy = str(i)
                mm = str(j)
                if(j < 10): mm = '0' + str(j);

                temp = getRTMSDataSvcAptTrade(row[0],yy+mm,'인증키')
                silTrade = pd.concat([silTrade,temp])
silTrade.to_sql('sil_trade',con,if_exists='append',index=False)
    
con.close()

아래 sql을 실행하여 데이터 갯수를 확인합니다.

select count(*) from sil_trade where 1=1

'Language > 파이썬' 카테고리의 다른 글

파이썬 공부를 위한 아나콘다 설치  (0) 2021.07.27

댓글()

[vue.js] 컴포넌트

Language/Vue.js|2021. 7. 26. 22:37

vue 컴포넌트

vue 는 컨포넌트로 시작해서 컨포넌트로 끝난다라고 생각하시면 됩니다.. 이 컨포넌트에 대해서 잘알고 있으면 앞으로 문법들이나 예제들을 보는데 도움이 될것 같아 정리해 보겠습니다.

 CBD(Component Based Development)

CBD 는 시스템을 일체형으로 구축하지 않고 레고 블록 부품 하나씩을 조립해서 큰 레고 블록을 만드는 것처럼 시스템의 구성요소들을 컨포넌트라는 작은 요소로 분리하여 하나씩 만들고 이를 조립해서 하나의 시스템을 만든다는 개념입니다.

아래 app 은 총 5개의 컨포넌트로 이루어져 있습니다.

  1. 팝업된 윈도우 자체가 컴포넌트 입니다. 이컨포넌트는 윈도우 제목과 창닫기 버튼이 있습니다. 창닫기 버튼을 클릭하면 창을 닫는 역할을 수행합니다.
  2. 메모 3,4,5를 가지고 있는 부모 컨포넌트 입니다. 2번 화면에서 데이터를 저장하고 메모리스트를 가지고 오는 로직이 들어 있지만 화면은 존재하지 않습니다.
  3. 메모 상단에 위치한 컨포넌트 입니다.
  4. 메모를 작성하는 컴포넌트 입니다. 제목과 내용을 입력받아 저장버튼을 클릭하면 입력받은 글을 부포 컨포넌트에게 전달합니다.
  5. 댓글 리스트 컨포넌트로 댓글 배열을 받아서 리스트업하고 수정이나 삭제 버튼을 클릭하면 부모에게 수정및 삭제 이벤트를 발생합니다

왜 이렇게 개발할까요 ? 그냥 하나로 개발하면 되는데 왜 복잡하게 이렇게 개발하는 걸까요 ? 만든 컴포넌트를 재사용하기 위해서 입니다. 위에 5번 댓글 컨포넌트는 상당히 많이 사용되죠 ? 메모 app 에서도 사용될수 있지만 게시판의 글 보기 app 에도 사용될수 있습니다. 같은 기능을 계속 개발한다면 시간도 많이 들어가고 유지보수 하기도 힘들꺼에요 예를 들어 모든 댓글의 아이콘을 바꾼다고 가정하면 이걸 일일이 찾아서 모두 변경해 줘야 되죠 하지만 컴포넌트를 불러와서 사용했다면 하나만 수정하면 모든 app 들의 아이콘이 한번에 변경됩니다. 컨포넌트 기반으로 개발하면 불필요한 코딩을 줄일수 있고 유지 보수도 용이해 집니다. 그리고 실력있는 고참 개발자분들이 컨포넌트를 잘 만들어 놓았다면 화면을 개발하는 개발자는 해당 app 에서 사용하는 데이터 모델과 비지니스 프로세스만 잘 구현하고 실제 구현에 필요한 개발공수는 줄어듭니다. 그래서 cbd 기반으로 개발을 진행합니다.

 

예제

아래와 같은 tab 컴포넌트는 여러화면에서 사용하는 컴포넌트 입니다. 이름이 default 로 선택되어져 있는데 "나이"가 default 선택된 탭을 하나더 만든다고 가정하면 컴포넌트를 사용하지 않으면 중복된 코드들이 존재 할수 있습니다. 이렇게 공통으로 사용하는 탭 같은경우에는 컨포넌트로 만들어서 active 되는 탭만 props 로 지정해서 넘겨주고 props 값에 따라 default 선택 탭을 변경하면 됩니다.

 

실습

EleTab.vue

<template>
  <div id="tab">
    <el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
      <el-tab-pane v-for="(item, index) in tabInfo" :key="index" :label="item" :name="item">
        {{ tabInfo.concat(',') }} 중 {{item}}
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
 
<script>
export default {
  name: "EleTab",
  props: {
    tabInfo: Array,
    active : String,
  },
  data() {
    return {
      activeName : ''
    }
  },
  methods: {
    handleClick() {
      this.$emit("ele-tab-click",this.activeName);
    }
  },
  watch: {
    active: {
      immediate: true,
      deep: true,
      handler(newValue, oldValue) {
        if(newValue !== oldValue) this.activeName = newValue;
      }
    }
  }
}
</script>
 
<style scoped></style>

Page6.vue

<template>
  <div>
    <el-row>
      <el-col :span="24">
        하위 컴포넌트가 전달한값 : {{ sendData }}
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <ele-tab @ele-tab-click="handleClick" :tabInfo="[ '이름' , '나이' , '성별' , '하는일']" active="이름" />
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <ele-tab @ele-tab-click="handleClick" :tabInfo="[ '이름' , '나이' , '성별' , '하는일']" active="나이" />
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24">
        <ele-tab @ele-tab-click="handleClick" :tabInfo="[ '지역' , '기업' , '종교' , '취미' ,'기타1', '기타2']" active="취미" />
      </el-col>
    </el-row>
  </div>
</template>
 
<script>
import EleTab from "@/components/EleTab";
export default {
  name: "Page6",
  components: {
    EleTab
  },
  methods: {
    handleClick(data) {
      this.sendData = data;
    }
  },
  data() {
    return {
      sendData : '',
    }
  }
}
</script>
 
<style scoped></style>

코드설명

EleVue 컴포넌트는 element-ui 컴포넌트중 탭 컴포넌트를 사용했고 Page6.vue에서 만든 해당 컴포넌트를 재활용하는 형태로 구현했습니다.

댓글()

[vue.js] 소개

Language/Vue.js|2021. 7. 26. 21:16

Vue.js 소개

Vue.js는 React.js와 함께 가장 인기있는 자바스크립트 프레임워크 중의 하나입니다. 아래 Vue 의 Market Position 을 확인해 보면 React 보다는 조금 떨어지지만 많이 사용하고 있는 라이브러리임을 확인 할수 있습니다.

 

Vue.js는 React.js 보다 배우기 쉽다는 장점 때문에 지속 성장하는 추세입니다. 아래는 웹사이트에 채택하는 자바스크립트 트랜드를 보여 주는 표입니다. Vue.js 대비 어려운 Angular 는 떨어지고 React 는 상승세 이긴 하지만 vue js 보다는 상승세가 높지 않네요.

 

Vue.js 한국어 사이트https://kr.vuejs.org/ (opens new window)에 가보면 문서 번역이 잘되어 있습니다. 하지만 생각보다 예제가 많지 않았습니다. 그래서 vue.js 강좌를 진행하면서 기술을 정리하고 예제도 많이 만들어서 Vue.js로 멋진 Single Page Application 을 만들어 보겠습니다.

 

카운터 증가/감소 예제

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>vue.js 강좌 연습</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>

<div id="counter">
  Counter: {{ counter }}
   <button v-on:click="countPlus">카운터증가</button>
   <button v-on:click="countMinus">카운터감소</button>
</div>

<script>
const Counter = {
  data() {
    return {
      counter: 0
    }
  },
  methods : {
  	countPlus() {
  		this.counter++;
  	},
  	countMinus() {
  		this.counter--;
  	}
  }
}

Vue.createApp(Counter).mount('#counter')</script>

</body>
</html>

실행결과

버튼을 클릭하면 카운터가 증가/감소 되는 것을 확인 할수 있습니다.

 

 

댓글()

[vue.js] 개발 환경 구축하기

Language/Vue.js|2021. 7. 25. 18:55

vue.js 개발 환경 구축하기

Vue.Js Frontend 개발을 위한 환경 설정 방법에 대해서 알아 보겠습니다.

 

Visual Studio Code 설치

  1. 설치 파일을 다운로드 합니다.
  2. 다운로드 받은 파일을 더블 클릭하여 설치를 진행합니다.

동의합니다를 선택하여 [다음][다음] 을 클릭하여 설치를 완료합니다

 

Visual Studio Extension 설치

vscode 에서 사용하는 vue.js 관련 유용한 플러그인을 설치합니다.

  1. Vetur Extension : Vetur 플러그인은 Linting , Syntax-highlighting , Formatting등을 지원해 줍니다

vue peek Extention : vue콤포넌트를 통해 해당 콤포넌트 파일을 열어서 바로 수정할수 있는 기능을 지원해줍니다.

vue 2 snippets exteion : vue 코드 자동 완성 기능을 지원해줍니다

Chrome Plug-in 설치하기

크롬 플러그인이 설치되어 있으면 Vuex 를 사용시 컴포넌트의 상태변경을 추적할수 있으면 해당 상태 변경을 임의되로 변경하여 테스트 해볼수 있습니다. 아래 url 로 접속 하여 플러그인을 설치 합니다.

https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd

 

node.js 설치

https://nodejs.org/ko/ (opens new window)사이트에 접속하신후 LTS 안정버전을 다운로드 받아서 설치를 진행합니다. 다음 다음을 클릭하여 default 로 설치합니다.

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

아래 명령어로 버전이 확인되면 정상 설치 완료된 상태 입니다.

node --version
v15.3.0

※ windows 한글깨짐 관련 문제는 아래 url 을 참고하세요.

vue-cli 를 설치합니다.

npm i -g vue-cli

 

초기 프로젝트를 생성 합니다.

vue init webpack vstart
cd vstart
npm run dev

프로젝트가 정상적으로 생성되면 아래와 같은 그림을 볼수 있습니다.

 

'Language > Vue.js' 카테고리의 다른 글

[vue.js] vue-router 사용하기  (0) 2021.08.01
[vue.js] BASE_URL public_path 변경하기  (0) 2021.08.01
[vue.js] vue element-ui(ui 컴포넌트) 설치 및 사용  (0) 2021.07.31
[vue.js] 컴포넌트  (0) 2021.07.26
[vue.js] 소개  (0) 2021.07.26

댓글()

진법 변환

Language/c 언어|2021. 7. 24. 22:22

 

진법변환 소스 입니다.

 

void changeNumber(int arr[16], int number,int to) {
    int idx = 16;
    while (number > 0) {
        arr[idx--] = number % to;
        number /= to;
    }
    arr[idx] = number;
}

 

댓글()