Yahoo天気情報をElasticsearchへ登録してみました

ElasticsearchのKibanaでデータを可視化したかったので、
JavaでYahooの天気情報を取得してElasticsearchへ登録してみました。






Yahoo API 使用準備



下記にAPIを利用するための手順が書いてあります。



developer.yahoo.co.jp





手順5まで書いてありますが、今回は下記の2つだけで大丈夫でした。




  • Yahoo JAPAN IDの取得


  • アプリケーションを登録





アプリケーションの登録では、アプリケーション名やサイトURLは適当に設定し、
種類で「サーバーサイド(Yahoo! ID連携 v2)」を選択します。

アプリケーションを登録すると「Client ID」が発行されるので控えておきます。






気象情報APIの呼び出し



下記のAPIを使いました。
他にも色々な情報が取得できるようです。



developer.yahoo.co.jp





URLのパラメーターcoordinatesには緯度経度を設定します。(今回は東京駅)

outputは出力形式を設定します。デフォルトではxmlになっているのでjsonを設定しました。




/**
* Yahoo天気情報を取得する
*
* @return Yahoo天気情報
*/
public YahooWeather getWeather() {

try {
URL url = new URL("https://map.yahooapis.jp/weather/V1/place?coordinates=139.767052,35.681167&output=json&appid={自分のClient ID}");

try {
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
// リダイレクトを自動で許可しない設定
con.setInstanceFollowRedirects(false);
con.connect();

InputStream inputStream = con.getInputStream();

StringBuilder src = new StringBuilder();

while (true) {
byte[] line = new byte[1024];
int size = inputStream.read(line);
if (size <= 0) {
break;
}
src.append(new String(line, "utf-8"));
}

// Jsonをオブジェクトに変換
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(src.toString().trim()).getAsJsonObject();
Gson gson = new Gson();

return gson.fromJson(gson.toJson(json), YahooWeather.class);

} catch (IOException e) {
throw new RuntimeException("情報の取得に失敗しました");
}

} catch (MalformedURLException e) {
throw new RuntimeException("不正なURLです");
}
}





ちなみにGsonのインスタンスを作成するとき、下記のようにするとjsonが整形されて出力されます。
デバッグ出力したいときに便利です。




Gson gson = new GsonBuilder().setPrettyPrinting().create();





jsonで受け取ったデータをオブジェクトに入れたかったので、
json構造に合わせてオブジェクトクラスも作成しました。




/**
* Yahoo天気情報
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class YahooWeather {

private final ResultAllWeather ResultInfo;
private final List<ResultOneWeather> Feature;
}


/**
* 天気情報のレスポンス結果まとめ
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class ResultAllWeather {

private final int Count;
private final int Total;
private final int Start;
private final int Status;
private final double Latency;
private final String Description;
private final String Copyright;
}


/**
* 天気情報のレスポンス結果1件
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class ResultOneWeather {

private final String Id;
private final String Name;
private final GeometryInfo Geometry;
private final PropertyInfo Property;
}


/**
* 拠点の場所(世界測地系)
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class GeometryInfo {

private final String Type;
private final String Coordinates;
}


/**
* 地点の詳細情報
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class PropertyInfo {

private final int WeatherAreaCode;
private final WeatherInfoList WeatherList;
}


/**
* 気象情報リスト
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class WeatherInfoList {

private final List<WeatherInfo> Weather;
}


/**
* 気象情報リスト
*/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class WeatherInfo {

private final String Type;
private final String Date;
private final double Rainfall;
}





APIから取得したデータをElasticsearchに登録します。




/**
* Elasticsearchへリクエストを送信する
*/
public void putElasticsearch(YahooWeather yahooWeather) {
Gson gson = new Gson();
RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build();

HttpEntity entity = new NStringEntity(
gson.toJson(yahooWeather), ContentType.APPLICATION_JSON);

try {
Response indexResponse = null;
indexResponse = client.performRequest(
"POST",
"/yahoo/weather/",
Collections.<String, String>emptyMap(),
entity);

System.out.println(EntityUtils.toString(indexResponse.getEntity()));

} catch (IOException e) {
throw new RuntimeException("リクエストの送信に失敗しました");
}
}





Kibanaで確認すると、登録されていることがわかります。



f:id:mtomitomi:20180120201744p:plain





ですが、何故かこのままだと全ての項目がString型になっていました。

グラフ化するときは、数値で並び替えをしたり計算をするので、このままだとグラフ化できません。

Javaのほうで項目のデータ型を変えてみても変化がなかったので、
下記手順を参考にしたらKibanaのほうで型を変更することができました。



www.shin0higuchi.com





グラフでの可視化についてはまた今度やろうと思います。