import json
import requests
import urllib.request as req
from bs4 import BeautifulSoup
import xmltodict
import pandas as pd
import json: JSON 데이터 형식을 다루기 위한 라이브러리입니다.
import requests: HTTP 요청을 보내고 응답을 받을 수 있는 라이브러리입니다.
import urllib.request as req: URL을 통해 데이터를 가져오기 위한 라이브러리입니다.
import BeautifulSoup: HTML/XML 데이터를 파싱하기 위한 라이브러리입니다.
import xmltodict: XML 데이터를 Python 딕셔너리 형태로 변환하기 위한 라이브러리입니다.
import pandas as pd: 데이터 분석과 조작을 위한 라이브러리로, DataFrame이라는 자료구조를 제공합니다.
# 1) 본인의 인증키(Decoding 버전)
serviceKey = '키주소'
# 2) 서비스 URL
url = "http://apis.data.go.kr/1613000/RTMSDataSvcAptTradeDev/getRTMSDataSvcAptTradeDev?"
serviceKey: 공공데이터 포털에서 제공된 API 사용을 위한 인증키입니다.
url: 아파트 실거래 데이터를 제공하는 공공데이터 API의 기본 URL입니다.
# 3) API 요청변수(Request Parameter)
pageNo = '1'
numOfRows = '5'
DEAL_YMD = "202001" # 필요한 데이터의 연도 + 월
LAWD_CD = '11110' # 법정동 코드 앞자리 5글자 = 법정 구코드 (서울특별시 종로구)
pageNo: API 요청 시 데이터를 가져올 페이지 번호입니다. 첫 페이지를 가져오기 위해 1로 설정합니다.
numOfRows: 한 페이지에서 가져올 데이터의 수를 의미하며, 여기서는 5개로 설정되어 있습니다.
DEAL_YMD: 데이터의 연도와 월을 의미하며, 202001은 2020년 1월을 나타냅니다.
LAWD_CD: 법정동 코드입니다. 11110은 서울특별시 종로구를 나타냅니다.
payload = "serviceKey=" + serviceKey + "&" + \
"pageNo=" + pageNo + "&" + \
"numOfRows=" + numOfRows + "&" \
"LAWD_CD=" + LAWD_CD + "&" + \
"DEAL_YMD=" + DEAL_YMD + "&"
res = requests.get(url + payload)
data = json.loads(json.dumps(xmltodict.parse(res.text)))
print(data)
payload: API 요청에 필요한 파라미터들을 조합하여 하나의 문자열로 만듭니다.
requests.get(url + payload): 위에서 만든 url + payload로 HTTP GET 요청을 보내 데이터를 가져옵니다.
xmltodict.parse(res.text): XML 형식의 응답을 Python 딕셔너리로 변환합니다.
json.dumps(xmltodict.parse(res.text)): 딕셔너리 형식을 JSON 문자열로 변환합니다.
json.loads(json.dumps(...)): JSON 문자열을 다시
Python 객체로 변환하여 data 변수에 저장합니다.
print(data): 가져온 데이터를 출력합니다.

def getRTMSDataSvcAptTradeDev(pageNo,numOfRows,LAWD_CD,DEAL_YMD,serviceKey):
url="http://apis.data.go.kr/1613000/RTMSDataSvcAptTradeDev/getRTMSDataSvcAptTradeDev?"
payload = "serviceKey=" + serviceKey + "&" + \
"pageNo=" + pageNo + "&" + \
"numOfRows=" + numOfRows + "&" \
"LAWD_CD=" + LAWD_CD + "&" + \
"DEAL_YMD=" + DEAL_YMD + "&"
getRTMSDataSvcAptTradeDev 함수: API 요청을 보내고 받은 데이터를 처리하여 DataFrame으로 반환하는 함수입니다.
url, payload: API 요청을 위한 URL과 파라미터를 설정합니다.
xml = req.urlopen(url + payload)
result = xml.read()
soup = BeautifulSoup(result, 'lxml-xml')
items = soup.findAll("item")
aptTrade = pd.DataFrame()
temp = []
req.urlopen(url + payload): URL에 요청을 보내 XML 데이터를 가져옵니다.
result = xml.read(): XML 데이터를 읽습니다.
BeautifulSoup(result, 'lxml-xml'): 가져온 XML 데이터를 파싱하기 위해 BeautifulSoup 객체로 변환합니다.
items = soup.findAll("item"): XML 데이터에서 태그를 가진 모든 요소를 찾아 리스트로 반환합니다.
aptTrade = pd.DataFrame(): 데이터를 저장할 빈 DataFrame을 생성합니다.
temp = []: 데이터를 임시로 저장할 리스트입니다.
for item in items:
try:
년 = item.find("dealYear").text if item.find("dealYear") else "" # 계약년도
월 = item.find("dealMonth").text if item.find("dealMonth") else "" # 계약월
일 = item.find("dealDay").text if item.find("dealDay") else "" # 계약일
도로명 = item.find("roadNm").text if item.find("roadNm") else "" # 도로명
법정동 = item.find("umdNm").text if item.find("umdNm") else "" # 법정동코드
아파트 = item.find("aptNm").text if item.find("aptNm") else "" # 아파트단지명
건축년도 = item.find("buildYear").text if item.find("buildYear") else "" # 건축년도
층 = item.find("floor").text if item.find("floor") else "" # 층
거래금액 = item.find("dealAmount").text if item.find("dealAmount") else "" # 거래금액(만원)
도로명건물본번호코드 = item.find("roadNmBonbun").text if item.find("roadNmBonbun") else "" # 도로명건물본번호코드
도로명건물부번호코드 = item.find("roadNmBubun").text if item.find("roadNmBubun") else "" # 도로명건물부번호코드
도로명시군구코드 = item.find("roadNmSggCd").text if item.find("roadNmSggCd") else "" # 도로명시군구코드
도로명일련번호코드 = item.find("roadNmSeq").text if item.find("roadNmSeq") else "" # 도로명일련번호코드
도로명지상지하코드 = item.find("roadNmbCd").text if item.find("roadNmbCd") else "" # 도로명지상지하코드
도로명코드 = item.find("roadNmCd").text if item.find("roadNmCd") else "" # 도로명코드
법정동본번코드 = item.find("bonbun").text if item.find("bonbun") else "" # 법정동본번코드
법정동부번코드 = item.find("bubun").text if item.find("bubun") else "" # 법정동부번코드
법정동시군구코드 = item.find("sggCd").text if item.find("sggCd") else "" # 법정동시군구코드
법정동읍면동코드 = item.find("umdCd").text if item.find("umdCd") else "" # 법정동읍면동코드
법정동지번코드 = item.find("landCd").text if item.find("landCd") else "" # 법정동지번코드
일련번호 = item.find("aptSeq").text if item.find("aptSeq") else "" # 단지 일련번호
전용면적 = item.find("excluUseAr").text if item.find("excluUseAr") else "" # 전용면적
지번 = item.find("jibun").text if item.find("jibun") else "" # 지번
지역코드 = item.find("LAWD_CD").text if item.find("LAWD_CD") else "" # 지역코드
# 데이터를 리스트로 저장
items_data = [
년, 월, 일, 도로명, 법정동, 아파트, 건축년도, 층, 거래금액,
도로명건물본번호코드, 도로명건물부번호코드, 도로명시군구코드,
도로명일련번호코드, 도로명지상지하코드, 도로명코드,
법정동본번코드, 법정동부번코드, 법정동시군구코드, 법정동읍면동코드,
법정동지번코드, 일련번호, 전용면적, 지번, 지역코드
]
temp.append(items_data) # 리스트에 추가
except Exception as e:
# 에러 발생시 continue로 넘어감
print(f"Error processing item: {e}")
continue
temp = pd.DataFrame(temp,columns=["년","월","일","도로명","법정동","아파트","건축년도","층","거래금액","도로명건물본번호코드","도로명건물부번호코드","도로명시군구코드","도로명일련번호코드","도로명지상지하코드","도로명코드"
,"법정동본번코드","법정동부번코드","법정동시군구코드","법정동읍면동코드","법정동지번코드","일련번호","전용면적","지번","지역코드"])
aptTrade = pd.concat([aptTrade,temp])
aptTrade = aptTrade.reset_index(drop=True)
return aptTrade
serviceKey = "코드주소"
pageNo = '1'
numOfRows = '10000'
DEAL_YMD = '202312' # 필요한 데이터의 연도 + 월
LAWD_CD = '11470' # 법정동 코드의 앞자리 5글자 = 법정 구코드 (서울특별시 양천구)
asset = getRTMSDataSvcAptTradeDev(pageNo,numOfRows,LAWD_CD,DEAL_YMD,serviceKey)
asset
거래금액
# 거래금액 컬럼 type 변경
asset.dtypes
asset['거래금액'] = asset['거래금액'].str.replace(",", "")
asset = asset.astype({'거래금액':int})
asset = asset.astype({'전용면적':float})
# 전용면적 평으로 변경
asset['전용면적_평'] = asset['전용면적']/3.3
# 평당 거래금액 min, mean, max
asset_max = asset[['법정동','거래금액']].groupby('법정동').max()
asset_min = asset[['법정동','거래금액']].groupby('법정동').min()
asset_avg = asset[['법정동','거래금액','아파트','전용면적','전용면적_평']].groupby(['법정동','아파트','전용면적','전용면적_평']).mean()
asset_avg_r = asset_avg.reset_index()
asset_avg_r['평당_실거래가'] = asset_avg_r['거래금액']/asset_avg_r['전용면적_평']
신시가지 키워드로 검색
keyword = '신시가지'
asset_avg_r_key = asset_avg_r[asset_avg_r.아파트.str.contains(keyword)]
asset_avg_r_key.sort_values(by=['평당_실거래가'], axis=0, ascending=False)
import pandas as pd
file = 'C:/주소자세히/jscode20240801(말소코드포함)/KIKmix.csv'
# 인코딩을 cp949로 시도
try:
code = pd.read_csv(file, sep=',', encoding='cp949')
print("File read successfully with cp949 encoding")
except UnicodeDecodeError:
# cp949 인코딩 실패 시 euc-kr로 시도
try:
code = pd.read_csv(file, sep=',', encoding='euc-kr')
print("File read successfully with euc-kr encoding")
except UnicodeDecodeError:
print("Failed to read the file with cp949 and euc-kr encodings")
말소일자 결측치
code = code[code['말소일자'].isna()]
#말소일자가 결측치인 것을 가져옴
주소병합
# 주소 병합 함수
def merge_address(row):
# 각 부분을 결합하면서, 중복되지 않는 경우에만 추가
parts = [row['시도명']]
if pd.notna(row['시군구명']) and row['시군구명'] != row['동리명']:
parts.append(row['시군구명'])
if pd.notna(row['읍면동명']):
parts.append(row['읍면동명'])
if pd.notna(row['동리명']) and row['시도명'] != row['동리명']:
parts.append(row['동리명'])
return ' '.join(parts)
# '주소' 컬럼 생성
code['주소'] = code.apply(merge_address, axis=1)
code.head(2)
code.info()
## 구 이름을 입력하면 법정동 코드를 찾아보자
gu = 'OO'
def find_gu(gu) :
gu_code = code[code['주소'].str.contains(gu)]
gu_code = gu_code['법정동코드'].reset_index(drop = True)[0]
gu_code = gu_code[0:5]
#print(gu_code)
return ```
gu_code
find_gu('ㅇㅇ')
year = [str("%04d" %(y)) for y in range(2011, 2023)]
month = [str("%02d" %(m)) for m in range(1, 13)]
yyyymm_list = ["%s%s" % (y, m) for y in year for m in month]
yyyymm_list
def yr_list(fy, ty, fm, tm):
year = [str("%04d" %(y)) for y in range(fy, ty+1)]
month = [str("%02d" %(m)) for m in range(fm, tm+1)]
yyyymm_list = ["%s%s" % (y, m) for y in year for m in month]
#print(yyyymm_list)
return yyyymm_list
yyyymm_list = yr_list(2021,2023,1,12)
apt_Trade = pd.DataFrame()
LAWD_CD = find_gu('계양')
pageNo = '1'
numOfRows = '10000'
yyyymm_list = yr_list(2021,2023,1,12)
for yyyymm in yyyymm_list :
DEAL_YMD = yyyymm
temp = getRTMSDataSvcAptTradeDev(pageNo,numOfRows,LAWD_CD,DEAL_YMD,serviceKey)
print('작업(YMD) : %s, 데이터건수 : %s ' %(DEAL_YMD, temp.shape))
apt_Trade = pd.concat([apt_Trade, temp]).reset_index(drop = True)
apt_Trade.shape
apt_Trade_asset = apt_Trade
apt_Trade_asset.dtypes
apt_Trade_asset['거래금액'] = apt_Trade_asset['거래금액'].str.replace(",", "")
apt_Trade_asset = apt_Trade_asset.astype({'거래금액':int})
apt_Trade_asset = apt_Trade_asset.astype({'전용면적':float})
aptTrade_asset['전용면적평'] = apt_Trade_asset['전용면적']/3.3
aptTrade_asset_max = apt_Trade_asset[['법정동','거래금액']].groupby('법정동').max()
apt_Trade_asset_min = apt_Trade_asset[['법정동','거래금액']].groupby('법정동').min()
apt_Trade_asset_avg = apt_Trade_asset[['법정동','거래금액','아파트','전용면적','전용면적평']].groupby(['법정동','아파트','전용면적','전용면적_평']).mean()
aptTrade_asset_avg_r = apt_Trade_asset_avg.reset_index()
apt_Trade_asset_avg_r['평당실거래가'] = aptTrade_asset_avg_r['거래금액']/apt_Trade_asset_avg_r['전용면적평']
aptTrade_asset_avg_r.sort_values(by=['평당실거래가'], axis=0, ascending=False)
aptTrade_asset_avg_r.sort_values(by=['평당실거래가'], axis=0, ascending=False)
apt_Trade.to_excel('C:/주소/pyhome/aptTrade.xlsx', sheet_name = LAWD_CD, index = False)
#파일 두개 다운
with pd.ExcelWriter('C:/Users/506-405/바탕 화면/pyhome/output.xlsx') as writer:
aptTrade.to_excel(writer, sheet_name=LAWD_CD, index=False)
apt_Trade_asset_avg_r.to_excel(writer, sheet_name='평당실거래가', index=False)
apt_Trade_asset_avg_r.head()
apt_Trade_asset_avg_r.head()