농업기상 관측데이터 API 활용하기
데이터 준비
취미로 하는 분석에서 기상 데이터가 필요해졌다. 그래서 농업기상 관측데이터를 가져오기로 했다.
encodingKey
사이트에 들어가서 활용신청을 누르고, encodingKey를 얻었다. 프로젝트 디렉토리에 잘 저장을 해두고, 다음과 같이 불러온다.
import requests
from xml.etree import ElementTree
import pandas as pd
# get key
encodingKey = ''
decodingKey = ''
with open("./personal/weather.txt", "r") as f:
encodingKey = f.readline()
decodingKey = f.readline()
encodingKey = encodingKey.replace('\n', '')
url 생성
이제 필요한 정보를 가져오기위한 url을 생성해야 한다. 정해진 양식에 맞춰서 url링크를 준비한다.
def mk_page_url(yr, mon, page, size=100):
# make url
url = 'http://apis.data.go.kr/1390802/AgriWeather/WeatherObsrInfo/GnrlWeather/getWeatherMonDayList'
this_mon = str(mon) if mon >= 10 else ('0'+str(mon))
queryParams = '?serviceKey=' + encodingKey + \
'&Page_No=' + str(page) + \
'&Page_Size=' + str(size) +\
'&search_Year=' + str(yr) + \
'&search_Month=' + this_mon
return url + queryParams
XML 파싱
API를 통해 받아오는 결과는 xml형식이다. 그래서 이것을 파싱해서 원하는 값만 들고온 후, 작업하기 편한 DataFrame으로 만들었다.
# get monthly
def get_monthly_weather_once(myurl):
response = requests.get(myurl)
root = ElementTree.fromstring(response.content)
if root[0][0].text == '200':
this_df = pd.DataFrame()
for body in root.iter('body'):
for items in body.iter('items'):
for item in items.iter('item'):
tmp_dict = {}
for i in item:
tmp_dict[i.tag] = i.text
tmp_df = pd.DataFrame.from_records([tmp_dict])
this_df = this_df.append(pd.DataFrame(tmp_df))
return this_df
else:
print("\n")
print(root[0][0].text)
print("에러 코드를 확인하세요!")
필요 데이터 받아오기
지금까지 만든 함수들을 조합해서 특정 ‘년월’에 해당하는 데이터 전체를 받아오는 함수를 만들었다.
def get_monthly_weather(year, mon):
print(year,"년 ",mon,"월 데이터 수집 시작 >>> ", end='')
cond = True
start_num = 1
my_df = pd.DataFrame()
while cond:
try:
full_url = mk_page_url(year, mon, start_num)
tmp_df = get_monthly_weather_once(full_url)
my_df = my_df.append(tmp_df)
cond = len(tmp_df)
start_num += 1
except:
print(start_num,"번 페이지에서 에러나서 종료:( \n")
break
print("수집 끝!!")
return my_df
저장
이제 실제로 데이터를 받아와서 한 번에 저장해보자. 운영계정을 받으면 한 번에 필요한 대용량 데이터를 모두 내릴 수 있다.
# 학습 전체기간 저장
for y in range(2016,2021):
for m in range(1,13):
weather_df = get_monthly_weather(y, m)
weather_df = weather_df.drop_duplicates()
weather_df.to_csv(f'./data/weather/weather_{y}_{m}.csv', encoding='cp949')