기상청에서는 다양한 기상자료들을 다운로드 받을 수 있는 API 허브 서비스를 제공합니다. ASOS, AWS 등의 지상관측 자료 뿐만 아니라, 레이더, 위성, 수치 모델 격자자료들도 하나의 사이트에서 통합적으로 API를 통해 받을 수 있습니다.
따라서 기상청 API허브를 이용해 자료를 다운로드 받는 방법을 기록하고자 합니다.
💡 Github 에서 코드를 확인할 수 있습니다.
1. 계정 만들기 및 자료 활용 신청
기상청 API허브 사이트에 들어가서 회원가입을 합니다. 메일 인증을 통해 가입이 진행됩니다.
로그인 후 다운받고자 하는 자료를 활용 신청해야합니다.
저는 지상관측-종관기상관측(ASOS) 메뉴로 들어가서 “시간자료”와 “시간자료(기간 조회)”를 활용 신청하였습니다. 오른쪽에 API 활용신청 버튼을 누르고, 활용 분야 및 목적을 입력하시면 신청이 완료됩니다.
2. Python을 이용해 API 호출 url 만들기
API를 이용해 자료를 받기 위해서는 사용자가 ‘요청인자’를 모두 지정하여야 합니다. 요청인자들은 데이터 종류별로 다 다르며 기상청 API허브 사이트에 잘 정리되어 있습니다. ASOS 시간자료(기간 조회)를 받기위해 필요한 요청인자는 다음과 같습니다.
인자명 | 설명 |
---|---|
tm1 | 시작시간 년월일시분(KST) : YYYYmmddHHMM |
tm2 | 종료시간 년월일시분(KST): YYYYmmddHHMM |
stn | ASOS 지점 번호 (전체지점 다운받으려면 0) |
help | 변수 설명 도움말 (0: 도움말 없음, 1: 도움말 있음) |
authKey | 발급된 API 인증키 |
API 인증키는 마이페이지에 가면 “인증키 현황”에 자신의 인증키가 있습니다.
이 요청인자들을 이용해서 API호출을 하기 위한 url 주소를 만들어야 합니다. url의 구조는 다음과 같습니다.
ASOS 시간자료(기간 조회)를 제공하는 도메인 주소를 입력하고 물음표(?)를 붙인 다음, 사용자가 지정한 요청인자들을 차례대로 붙이는 구조입니다. 이러한 url을 파이썬을 이용해 만들어보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def create_url(authKey, category, **kwargs):
url = f'https://apihub.kma.go.kr/api/{category}?'
for key, value in kwargs.items():
url += f'{key}={value}&'
url += f'authKey={authKey}'
return url
authKey='MY API KEY'
category='typ01/url/kma_sfctm3.php' # ASOS data domain
params={
"tm1": 202308010000,
"tm2": 202308012359,
"stn": 0,
"help": 0,
}
url = create_url(authKey, category, **params)
API호출을 위한 url이 생성 되었습니다.
생성된 url에 접속하면 데이터들을 볼 수 있습니다.
help=1 일때
3. API 호출한 ASOS 자료 데이터 프레임으로 만들기
만들어진 url주소를 이용하여 API 호출을 통해 데이터를 받아옵니다. 파이썬의 requests
패키지를 이용하여 쉽게 받아올 수 있습니다.
1
2
import requests
import pandas as pd
1
2
response = requests.get(url)
res_txt = response.text #데이터를 문자열로 바꿈
문자열로 받아온 데이터는 가공 작업을 통해 관측자료만 추출합니다.
1
2
3
lines = res_txt.strip().split('\n')
data_rows = [line.split() for line in lines]
data = data_rows[4:-1]
data_rows[4:-1]
부분은, header를 제외한 자료가 시작하는 부분이 4번째 줄 부터이고, 끝나는 지점이 아래에서 두번째 줄 (#7777END 윗줄)이므로 이렇게 지정하였습니다.
다음으로는 자료의 header를 만들어 보겠습니다.
help=0
으로 하여 API 호출한 자료를 보게 되면, 두줄로 된 header가 있는 모습을 볼 수 있습니다. 첫번째 줄(# YYMMDDHHMI STN WD WS GS...
)은 변수 명, 두번째 줄(# KST ID 16...
)은 단위를 의미합니다. 첫번째 줄로 header를 만들게 되면 column명이 중복되는 부분이 있어 에러가 발생합니다. 따라서 저는 url의 help=1
로 하여 도움말에 나타나는 변수명들을 이용해 header를 만들고자 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def create_header(url):
url = url.replace('help=0','help=1')
response = requests.get(url)
res_txt = response.text
lines = res_txt.strip().split('\n')
for line_number, line in enumerate(lines):
if '01234567890123456789' in line:
endline = line_number-1
break
header_rows = [line.split() for line in lines[4:endline]]
header=[]
for i in header_rows:
header.append(i[2])
return header
header = create_header(url)
우선, 이미 만들어진 url의 help=1
로 고치고, 받아온 문자열 데이터들을 줄바꿈을 해줍니다. 그리고 도움말 뒤에 항상 ‘0123456789’로 이루어진 숫자들이 나타난다는 점을 이용하여 도움말 부분을 추출한 다음, header를 생성하였습니다.
만들어진 data와 header를 사용해 데이터 프레임을 만듭니다.
1
2
# Make Dataframe
df = pd.DataFrame(data, columns=header)
다음 포스트에서는 받아온 데이터프레임을 sqlite3를 이용해 데이터베이스에 저장하는 법을 기록하도록 하겠습니다.