컴퓨터/Python

Python (18) - 공공데이터 API를 이용하여 기상청 날씨를 가져오자

달서비 2023. 6. 15. 21:55

예전에 디시인사이드 크롤러를 만든적이 있었습니다. 크롤러를 이용하여 웹사이트의 소스코드를 복사하고 해당 데이터를 가공하여 사용할수 있었습니다. 크롤링과 다르게 가공된 정보를 가져올수 있는  API가 있습니다. 정부에서 운영하는 공공데이터 API가 있는데 제공 데이터를 바탕으로 날씨를 알아보겠습니다.

 

공공데이터

하늘 - pixabay

공공데이터는 정부와 공공기관이 생산하거나 수집한 데이터입니다. 해당 데이터를 이용하여 공공기관이 업무를 하며 이를 통하여 시민들에게 서비스를 제공합니다. 예를 들어 교육, 사회복지, 문화관광, 교통 정보, 기상 등 다양한 정보를 가지고 있습니다.  이러한 데이터는 누구나 무료로 접근하고 사용할 수 있습니다. 각 기관에 투명성을 높여주어, 시민들에게 다양한 혜택을 줍니다. 개인이나 기업에서 이를 활용하여 다양한 프로그램, 서비스, 연구 등을 할 수 있습니다. 이러한 자료들은 정부나 공공기관의 웹사이트, 데이터 포털 등에서 정보를 제공합니다. 해당 플랫폼을 통하여 다양한 형식으로 데이터를 다운받거나, API를 받아 실시간으로 데이터를 가져올 수 있습니다.

 

아래는 공공데이터 포털의 링크입니다. 

https://www.data.go.kr/

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

 

API 인증키 발급방법

1. 우선 위에 있는 링크로 공공데이터 포털을 접속합니다.

공공데이터 포탈 웹사이트

 

2. API 사용을 위하여 로그인합니다.

공공데이터 포탈 로그인 화면

3. 로그인 후 사용하고 싶은 오픈 API를 찾습니다.

여기서 단기예보를 사용할 것이기 때문에 기상청_단기예 ((구)_동네예보) 조회 서비스를 사용하겠습니다.

 

4. 클릭 후 활용신청 버튼을 누르도록 합니다.

오픈 API 상세화면

여기서 추가로 참고 문서를 다운로드 하도록 합니다. 해당 알집 파일 안에는 API 사용 방법이 적혀있습니다.

 

5. 활용 목적 등을 선택하여 신청하도록 합니다.

서비스 신청 중인 화면

밑에 상세기능정보 선택이 있는데 자신이 선택하고 싶은 것을 선택합니다. 활용목적 등 정보를 입력하고 신청하면 API키를 줍니다. 상세 기능 정보 선택에서 초단기 예보는 체크하도록 합니다. (사용하는 코드)

 

 

6. 키 발급 (마이페이지 - 오픈 API - 인증키 발급현황)

활용신청 현황 화면

해당 화면 아래에 지금 사용하고 있는 화면을 클릭하면 계발계정 상세보기 탭이 나옵니다. 

개발계정 상세보기

여기서 일반 인증키가 API 인증키를 입니다. (보안을 위해 모자이크 처리를 하였습니다.) 각자 받은 인증키를 사용하면 됩니다.

 

7. 메뉴얼 보기

출처 - 기상청 단기예보 조회 서비스 OPEN API 활용 가이드

4번에서 알집 파일을 풀어보면 가이드북이 있습니다. 왼쪽은 API를 사용하기 위한 요청 메세지 명세고 오른쪽은 전달되는 데이터들입니다. 해당 데이터를 이용하여 설계를 해보도록 하겠습니다.

 

API를 사용해 보자

다양한 언어로 API를 활용할 수 있으나 저는 파이썬을 이용하여 API를 활용하려고 합니다. 

import requests
from datetime import datetime
import xmltodict

def get_current_date_string():
    current_date = datetime.now().date()
    return current_date.strftime("%Y%m%d")

def get_current_hour_string():
    now = datetime.now()
    if now.minute<45: # base_time와 base_date 구하는 함수
        if now.hour==0:
            base_time = "2330"
        else:
            pre_hour = now.hour-1
            if pre_hour<10:
                base_time = "0" + str(pre_hour) + "30"
            else:
                base_time = str(pre_hour) + "30"
    else:
        if now.hour < 10:
            base_time = "0" + str(now.hour) + "30"
        else:
            base_time = str(now.hour) + "30"

    return base_time

keys = '발급한 키'
url = 'http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtFcst'
params ={'serviceKey' : keys, 
         'pageNo' : '1', 
         'numOfRows' : '1000', 
         'dataType' : 'XML', 
         'base_date' : get_current_date_string(), 
         'base_time' : get_current_hour_string(), 
         'nx' : '55', 
         'ny' : '127' }

def forecast():
    # 값 요청 (웹 브라우저 서버에서 요청 - url주소와 파라미터)
    res = requests.get(url, params = params)

    #XML -> 딕셔너리
    xml_data = res.text
    dict_data = xmltodict.parse(xml_data)

    #값 가져오기
    weather_data = dict()
    for item in dict_data['response']['body']['items']['item']:
        # 기온
        if item['category'] == 'T1H':
            weather_data['tmp'] = item['fcstValue']
        # 습도
        if item['category'] == 'REH':
            weather_data['hum'] = item['fcstValue']
        # 하늘상태: 맑음(1) 구름많은(3) 흐림(4)
        if item['category'] == 'SKY':
            weather_data['sky'] = item['fcstValue']
        # 강수형태: 없음(0), 비(1), 비/눈(2), 눈(3), 빗방울(5), 빗방울눈날림(6), 눈날림(7)
        if item['category'] == 'PTY':
            weather_data['sky2'] = item['fcstValue']

    return weather_data

def proc_weather():
    dict_sky = forecast()

    str_sky = "서울 "
    if dict_sky['sky'] != None or dict_sky['sky2'] != None:
        str_sky = str_sky + "날씨 : "
        if dict_sky['sky2'] == '0':
            if dict_sky['sky'] == '1':
                str_sky = str_sky + "맑음"
            elif dict_sky['sky'] == '3':
                str_sky = str_sky + "구름많음"
            elif dict_sky['sky'] == '4':
                str_sky = str_sky + "흐림"
        elif dict_sky['sky2'] == '1':
            str_sky = str_sky + "비"
        elif dict_sky['sky2'] == '2':
            str_sky = str_sky + "비와 눈"
        elif dict_sky['sky2'] == '3':
            str_sky = str_sky + "눈"
        elif dict_sky['sky2'] == '5':
            str_sky = str_sky + "빗방울이 떨어짐"
        elif dict_sky['sky2'] == '6':
            str_sky = str_sky + "빗방울과 눈이 날림"
        elif dict_sky['sky2'] == '7':
            str_sky = str_sky + "눈이 날림"
        str_sky = str_sky + "\n"
    if dict_sky['tmp'] != None:
        str_sky = str_sky + "온도 : " + dict_sky['tmp'] + 'ºC \n'
    if dict_sky['hum'] != None:
        str_sky = str_sky + "습도 : " + dict_sky['hum'] + '%'

    return str_sky
    
print(proc_weather())

'''
서울 날씨 : 맑음
온도 : 19ºC
습도 : 95%
'''

현재 서울 날씨 정보를 텍스트로 나타내는 프로그램을 구현하였습니다. 여기서 각 함수의 역할은 다음과 같습니다.

  1. get_current_date_string() : 날짜 포맷으로 지정해 주는 함수
  2. get_current_hour_string() : 30분 단위로 단기예보가 있기 때문에 시간을 구분한다
  3. forecast() : API를 이용하여 정보를 가져오는 함수
  4. proc_weather() : forecast 함수로 받은 결과를 텍스트로 정리해주는 함수

 

날씨 API 말고도 정부에서는 많은 공공데이터를 제공합니다. 국내에서 발생하는 정보들을 이용하는 프로그램을 만들 때 다양하게 사용할 수 있습니다. 특히 부동산등 경제와 관련된 프로그램을 만들때 많이 유용할 것으로 예측합니다.