Python 공공데이터 API 저장 실습예제 (날씨 종관)

참고문서

사용 라이브러리 포함

from urllib.request import urlopen
from urllib.parse import urlencode, unquote, quote_plus
import urllib
import json
import pandas as pd
import time
import datetime

이하 API 코드

#조회할 첫 날짜 년,월,일,시,분,초
first_date = datetime.datetime(2011,1,1,0,0,0)
#조회할 마지막 날짜, 본 코드는 현 시간에서 하루를 뺀 일자를 입력했습니다. (사용한 API에서는 당일 하루 전 데이터까지만 제공하기때문)
last_date = datetime.datetime.now() - datetime.timedelta(days=1)
#지역 번호(지점번호) 지정
point = 165
now = first_date
#1년 후 날짜 계산
now_after_365 = now + datetime.timedelta(days=365)

#공공데이터 서비스 키 입력
servicec_key = "서비스키"
url = 'http://apis.data.go.kr/1360000/AsosHourlyInfoService/getWthrDataList'

#매년 데이터를 누적할 LIST 초기화
get_list = []
#마지막 년도가 증감 년도보다 작거나 같으면 루프 종료
while not last_date.year <= now.year:
    i = 1 #페이지 수 변수 초기화

    #마지막 일자일 경우 변수 지정
    if last_date.year == now.year+1:
        now_after_365 = last_date
    print(now.strftime("%Y%m%d"),now_after_365.strftime("%Y%m%d"))

    #페이지 루프
    while True:
        #API에 요청할 파라미터 정의
        params = '?'+urlencode({'serviceKey' : servicec_key,
                 'pageNo' : i,
                 'numOfRows' : '999', #최대 999개까지 가능
                 'dataType' : 'JSON',
                 'dataCd' : 'ASOS',
                 'dateCd' : 'HR',
                 'startDt' : now.strftime("%Y%m%d"),
                 'startHh' : '01',
                 'endDt' : now_after_365.strftime("%Y%m%d"),
                 'endHh' : '01',
                 'stnIds' : point
                 })
        #API 요청
        req = urllib.request.Request(url + unquote(params))
        #받아온 Response 데이터 읽기
        response_body = urlopen(req, timeout=60).read()
        #json 데이터로 읽기
        data = json.loads(response_body)
        #페이지에서 데이터가 없으면 break
        if data['response']['header']['resultMsg'] == "NO_DATA":
            break


        try:
            print("데이터 회신 성공",data['response']['header']['resultMsg'])

            get_list = get_list+  data['response']['body']['items']['item']
            print(len(get_list))
        except:
            print(data['response']['header']['resultMsg'])
            print("가져오기 실패 ----> 5초 기다린 후 재시도")
            time.sleep(5)
            req = urllib.request.Request(url + unquote(params))
            response_body = urlopen(req, timeout=60).read()

            data = json.loads(response_body)
            get_list = get_list+  data['response']['body']['items']['item']
            print(data)
        i = i+1
    #현 날자를 이전 마지막 날자 다음날로 설정
    now = now_after_365 + datetime.timedelta(days=1)
    #마지막날을 현 날자 1년뒤로 설정
    now_after_365 = now + datetime.timedelta(days=365)

    print("----> 5초 기다림")
    time.sleep(5)
#리스트 dataframe으로 변환
df = pd.DataFrame(get_list)
#데이터프레임 csv로 저장
df.to_csv('weather_'+str(point)+'_'+first_date.year+'_'+last_date.year+'.csv',encoding='utf-8-sig')
print(df)

+ 본 API에 너무 자주 데이터 요청을 하게 되면 잠시 거부 상태가 될 수 있기 때문에 Sleep을 한번씩 걸어줘야 합니다.
+ API에서 제공하는 날짜 범위 내, 지점 범위 내에 있는 데이터 변수만 사용하여야 에러 발생을 방지할 수 있습니다.

Leave a Comment