ElasticsearchのKibanaでデータを可視化したかったので、
JavaでYahooの天気情報を取得してElasticsearchへ登録してみました。
Yahoo API 使用準備
下記にAPIを利用するための手順が書いてあります。
手順5まで書いてありますが、今回は下記の2つだけで大丈夫でした。
Yahoo JAPAN IDの取得
アプリケーションを登録
アプリケーションの登録では、アプリケーション名やサイトURLは適当に設定し、
種類で「サーバーサイド(Yahoo! ID連携 v2)」を選択します。
アプリケーションを登録すると「Client ID」が発行されるので控えておきます。
気象情報APIの呼び出し
下記のAPIを使いました。
他にも色々な情報が取得できるようです。
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で確認すると、登録されていることがわかります。
ですが、何故かこのままだと全ての項目がString型になっていました。
グラフ化するときは、数値で並び替えをしたり計算をするので、このままだとグラフ化できません。
Javaのほうで項目のデータ型を変えてみても変化がなかったので、
下記手順を参考にしたらKibanaのほうで型を変更することができました。
グラフでの可視化についてはまた今度やろうと思います。