- 개요
저번 포스트에서는 기상청 API 허브에서 제공하는 기본 URL로 ASOS 시간 자료를 다운로드 했습니다.
그냥 기본 URL의 변수인 tm1(시작기간), tm2(종료기간)을 설정해서 ASOS 시간 자료를 다운로드 받아보면
ASOS 시간 자료는 최대 30일까지 받을 수 있다는 문제가 있습니다.
31일까지면 좋을텐데 30일이 최대입니다. ㅠㅠ
그러므로 장기간의 ASOS 시간 자료를 다운로드 받으려면 파이썬 코드로 한 번에 다운 받는 자료의 길이를 30일 이내로 여러 번 API를 요청해야 합니다.
이번 포스트에서는
# 1. 다운 받을 길이를 설정하고 이를 30일 이내의 기간으로 끊어서 tm1과 tm2을 설정하는 부분
# 2. 위의 함수를 기반으로 API를 여러 번 요청해서 하나의 파일로 저장하는 부분
이렇게 두 기능을 파이썬으로 구현해보겠습니다.
- 다운로드 받을 기간 설정 및 원하는 기간으로 기간을 분리하는 함수
from datetime import datetime, timedelta
def get_tm1_tm2(current_date, delta_day):
tm1 = current_date.strftime('%Y%m%d')+'0000'
current_date += timedelta(days=delta_day-1)
tm2 = current_date.strftime('%Y%m%d')+'2300'
current_date += timedelta(days=1)
return tm1, tm2, current_date
"""
현재 날짜(current_date)를 넣으면
현재 날짜를 tm1으로 반환,
delta_day-1 날짜 이후의 날짜를 tm2로 반환하고
delta_day 날짜 후의 date를 current_date로 업데이트함
delta_day = 10인 경우
2023년 1월 1일이 들어가면
tm1: 2023010100
tm2: 2023010923
>>> tm1~tm2는 10일치
current_date는 2023년 1월 11일로 업데이트 됨
"""
- 자료 다운로드 및 저장
import requests
import pandas as pd
key = '본인 키 입력'
outpath = './'
url_fmt = 'https://apihub.kma.go.kr/api/typ01/url/kma_sfctm3.php?tm1={}&tm2={}&stn={}&help=1&authKey={}'
stn_id = 108 # ASOS 관측소 번호 입력
start_date = datetime(2023, 1, 1) # 다운로드 시작 날짜
end_date = datetime(2023, 3, 31) # 다운로드 종료 날짜
delta_day = 10 # 한 번의 URL 요청시 받는 기간 (30일 이하로 설정해야 함)
current_date = start_date
"""
URL로 요청한 자료는 특정한 형식을 가지고 있어 바로 csv로 저장할 수 없습니다.
요청한 자료를 읽어보면 우리가 필요한 ASOS 자료의 위치는
54번째 행부터'#7777END'의 이전 행까지입니다.
"""
index_start = 54
end_string = '#7777END'
data_lines = []
run = True
while run:
tm1, tm2, current_date = get_tm1_tm2(current_date, delta_day)
"""
current_date가 end_date보다 미래인 경우 end_date까지 다운로드 받고
run=False로 while 루프 종료
"""
if end_date <= current_date:
tm2 = end_date.strftime('%Y%m%d')+'2300'
run = False
url = url_fmt.format(tm1, tm2, stn_id, key)
response = requests.get(url)
data = response.text
lines = data.splitlines()
# ASOS 자료의 시작 인덱스부터 끝 인덱스까지 값을 data_lines에 추가함
index_end = [index for index, line in enumerate(lines) if end_string in line]
data_lines.extend(lines[index_start:index_end[0]])
column_line = lines[index_start-2] # 칼럼 명은 index_start의 2행 전에 나옴
columns = column_line.split()
columns = columns[1:]
# DataFrame으로 변환 후 csv로 저장
df = pd.DataFrame([line.split() for line in data_lines], columns=columns)
df.to_csv(f'{outpath}ASOS_hourly_{108}.csv', index=False, header=True)
- 고려사항
저는 이번 포스트에서 하나의 관측소에 대해 2023년 1월부터 2023년 3월까지 3개월의 기간을 10일(delta_day)로 분리하여 여러 번 API 요청하여 하나의 list로 모든 자료를 합쳐서 하나의 파일로 저장했습니다.
만약 더 긴 기간 여러 관측소를 받는다고 치면 고려해야할 사항이 있습니다.
1. 하나의 key로 하루에 요청할 수 있는 API의 수는 최대 20000번입니다.
20000번이 엄청 많아보이지만 몇 십년 이상 자료를 받는다면 코드를 짤 때 API 요청 횟수를 신경써야합니다.
50년치는 약 18000일 정도 됩니다. 10일(delta_day)씩 끊어서 API를 요청하더라도 11개 ASOS 자료 밖에 못 받습니다.
이럴 땐 stn_id=0으로 모든 ASOS 자료를 받는 것도 하나의 방법입니다.
참고로 개인계정의 API 요청은 최대 20000번입니다. 기관이면 30000번까지 되는 것으로 알고 더 많이 요청하려면 기상청 API 허브 사이트에 따로 요청해야합니다.
2. 용량 문제
제 코드는 ASOS 자료를 csv 파일로 저장하는데 1달치 모든 ASOS 자료의 용량은 10mb가 조금 넘습니다.
모든 ASOS 자료를 10년 받으면 용량은 1기가가 넘습니다(10*12개월*10년 = 1200mb = 1.2 gb).
이런 경우 csv가 아니라 pkl로 저장하면 용량을 줄일 수 있습니다.
또한, 파이썬 코드가 돌아갈 때 메모리가 부족할 수도 있는데 이 때는 모든 자료를 하나의 파일로 저장하는 방식이 아닌 while 루프 안에 n번 API 요청할 때마다 파일을 저장하시길 바랍니다.
3. API 요청의 안정성 문제
가끔 API 요청을 했는데도 응답이 제대로 안 올 때가 있습니다. 그러면 아마 오류가 나면서 멈출 것입니다.
API 요청 제한 횟수, 용량 문제가 없다면 그냥 코드를 다시 돌리시면 되겠습니다.
'대기과학 > 프로그래밍' 카테고리의 다른 글
[MetPy] 튜토리얼: 알아보고 설치해보자 (1) | 2024.06.10 |
---|---|
지도에 바람 벡터 그리기 (0) | 2024.06.05 |
[기상청 API][ASOS 시간(hourly) 자료 다운로드] 1. 기본 제공 URL 사용 (0) | 2024.05.24 |
관측 자료의 결측을 시각화하기 (0) | 2024.05.22 |
[folium] matplotlib을 활용한 온도 공간 분포 시각화 (0) | 2024.05.14 |