다양한 주제

기상청 API 이용방법

patrick-star 2023. 7. 28. 17:48
728x90

기상청 API 허브 홈페이지

기상청에서 제공하는 날씨 데이터는 기상자료개방포털을 통해서 csv 형태로 데이터를 얻어내는 방법이 있다. 하지만, 이 방법은 원하는 데이터를 얻어야 할 때 마다 직접 홈페이지로 들어가서 csv로 다운을 받아야 하는 번거로운 작업을 해줘야 한다.

이에 대한 대안으로 기상청 API 허브를 이용할 수 있다.

상황

1) 지상관측 데이터를 받아온다.
2) Java를 이용해서 기상청 데이터를 csv 형태로 저장하려고 한다.
3) 회원가입을 하고나서 인증키까지 받아냈다.

URL 파악

지상관측 자료 중 기간 정해서 조회하는 URL을 살펴보겠다. - 시간자료(기간조회)

ex) https://apihub.kma.go.kr/api/typ01/url/kma_sfctm3.php?tm1=201512110100&tm2=201512140000&stn=108&help=1&authKey=myAuthKey

  • tm1 : 시작시간 또는 시작일 (default는 현재시간) - 형식 YYYYmmddHHMM 또는 YYYYmmdd
  • tm2 : 종료시간 또는 종료일 (default는 현재시간) - 형식 YYYYmmddHHMM 또는 YYYYmmdd
  • stn : 지점번호 (default는 0 또는 전체시점)
  • help : 도움말 추가 여부 (1이면 도움말 추가 / 0이거나 없으면 도움말 없음)
  • authKey : 발급된 API 인증키

이를 토대로 위에 있는 URL을 해석하면
지점번호 108번의 날씨 데이터 중에서 2015년 12월11일 01시 00분 ~ 2015년 12월 14일 00시 00분까지의 데이터를 도움말을 첨부해서 반환한다는 뜻이다.

해당 URL에서는 1시간 단위의 데이터를 제공한다.

데이터 예시

그렇다면, 이 데이터를 어떻게 csv로 가져올 수 있는지 살펴보겠다.

이용 방법

1. 원하는 경로에 csv 파일 지정

import java.io.BufferedWriter;
import java.io.FileWriter;

BufferedWriter bf = new BufferedWriter(new FileWriter("원하는 경로" + "/" + "원하는이름" +".csv", false));

// 결과값들을 저장할 StringBuilder
StringBuilder results = new StringBuilder(); 

2. URL을 통한 데이터 받아오기

import java.net.URL;
import java.net.HttpURLConnection;

import java.io.BufferedReader;
import java.io.InputStreamReader;

// 앞서 얘기한 URL이다. 
// 각각의 값은 모두 String 형태로 만들어서 추가하면 된다. 
// 여기서는 help가 필요없다고 판단해서 help 인수는 넣지 않았다. 
URL url = new URL("https://apihub.kma.go.kr/api/typ01/url/kma_sfctm3.php?" 
                        + "tm1=" + "시작시간" + "&tm2=" + "종료시간"
                        + "&stn=" + "지점번호" + "&authKey=" + "인증키"); 

HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 

connection.setRequestMethod("GET"); // 요청 메시지를 보낼 때 GET 메소드를 사용하도록 함

// http request를 통해 반환받은 데이터를 BufferedReader 자료형 변수 br에 저장
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));

3. 데이터 처리

앞서 데이터를 봤으면 알겠지만 불필요한 데이터가 존재하고 원하는 만큼 깔끔하게 데이터가 저장되는 건 아니라서
어느 정도의 후처리가 필요하다.

    1. 컬럼 정리
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;   

// 1,2번째 행을 버리기 위해서 readLine()으로 넘겨버렸다.  
br.readLine(); br.readLine();

// 3번째 행 = csv로 저장할 때 각 데이터의 이름들 = 컬럼의 헤더 값  
// 한 칸 띄어쓰기(" ")를 기준으로 구분되도록 StringTokenizer를 사용했다.  
List columnNames = new LinkedList<>();  
StringTokenizer st = new StringTokenizer(br.readLine());

st.nextToken(); // 3번째 행의 #은 버린다.

// 각각의 값을 리스트에 추가  
while(st.hasMoreTokens()) columnNames.add(st.nextToken());

// 한 칸씩 띄어쓰기 된 경우도 있지만  
// 2칸 이상 띄어쓰기 된 경우도 많기 때문에 아래와 같이 모든 컬럼 값들에 대해 replace를 해줘야 한다.  
String columnNamesString = columnNames.toString().replace(" ", "");

results.append(columnNamesString.substring(1, columnNamesString.length() - 1) + "\\n");

// 4번째 줄은 단위값인데 굳이 필요가 없다고 판단해서 버림  
br.readLine();
    1. 데이터 정리

String inputLine = null;  
List dataList = new LinkedList<>();

// 데이터 정리  
while((inputLine = br.readLine()) != null) {


    // 띄어쓰기로 구분된 값을 dataList에 저장
    st = new StringTokenizer(inputLine); 
    while(st.hasMoreTokens()) {
        dataList.add(st.nextToken()); 
    }

        // dataList에 있는 모든 값을 result에 추가하고 초기화
        results.append(dataList.toString().replace(" ", "").substring(1, dataList.toString().replace(" ", "").length() - 1) + "\n"); 

        dataList = new LinkedList<>();
}
    1. 파일 쓰기
br.close(); bf.flush();
bf.write(results.toString());

CSV 결과 예시

'다양한 주제' 카테고리의 다른 글

Windows 배치파일  (0) 2023.07.27
Windows 작업 스케줄러  (0) 2023.07.26
netstat에 대해  (0) 2023.07.25
scp에 대해(정의, 사용법, 비밀번호 없이 동작하도록 하는 방법)  (0) 2023.07.25
crontab  (0) 2023.07.20