📝

Yahoo!ジオコーダAPIで取得した座標をもとにleafletで地図に表示させる

2024/04/01に公開

はじめに

学習と趣味の一環でSuumoのスクレイピングを行ってみた。
Suumoでは物件一覧で住所が表示されているが、地図情報は一覧化されていない。
そのため、住所をもとに地図情報を表示させていきたいなと思い実装したので備忘録としてまとめる。

この記事でわかること

  1. Yahoo!ジオコーダAPIを使って、住所から座標を取得する
  2. leafletを使って、座標から地図にピン留めを行う

完成イメージ



こんな感じで、住所に対してピン留めされている。

Yahoo!ジオコーダAPIを使って住所から座標を取得する

これはジオコーダAPIを使う

Client ID: https://developer.yahoo.co.jp/start/
で利用手続きをした際に発行されるIDのこと。これに登録しなければ当APIは使えない。

query: ここに住所を入力する

東京都港区六本木の住所検索
https://map.yahooapis.jp/geocode/V1/geoCoder?appid=<あなたのClient ID(アプリケーションID)>&query=%e6%9d%b1%e4%ba%ac%e9%83%bd%e6%b8%af%e5%8c%ba%e5%85%ad%e6%9c%ac%e6%9c%a8

これでリクエストの準備はできた。

次はレスポンスであるが、
以下は、東京都港区六本木の住所検索のリクエストに対するレスポンスです。

<?xml version="1.0" encoding="UTF-8"?>
<YDF totalResultsReturned="1" totalResultsAvailable="1" firstResultPosition="1">
 <ResultInfo>
  <Count>1</Count>
  <Total>1</Total>
  <Start>1</Start>
  <Status>200</Status>
  <Description/>
  <Latency>0.054</Latency>
 </ResultInfo>
 <Feature>
  <Id>13103.29</Id>
  <Gid/>
  <Name>東京都港区六本木</Name>
  <Geometry>
   <Type>point</Type>
   <Coordinates>139.73359259,35.66288632</Coordinates>
...

ここで重要なのが、Coordinatesでありこれが今回欲している座標のことである。

Yahoo!ジオコーダAPIのリクエストパラメータ・レスポンスフィールドについて詳しく知りたい方は
Yahoo!ジオコーダAPI

をご覧ください。

これらをもとに実際にジオコーダAPIにリクエストを送り、レスポンスを受け取る処理がこちら。

OkHttpClient client = new OkHttpClient();
//APIキーは各自ご用意ください
String apiKey = System.getenv("YOPL_OPEN_API_KEY");
String place = "沖縄県那覇市具志3";
String url = "https://map.yahooapis.jp/geocode/V1/geoCoder?appid="+apiKey+"&query="+place+"&output=json";
Request request = new Request.Builder()
   .url(url)
   .build();

Response response = client.newCall(request).execute();
//レスポンスをjson文字列へ変換
String jsonStr =response.body().string();

そこからJsonNodeを使って座標を取得していく。
JsonNodeって何?って方は、こちらをご参照ください。
JavaでJsonNodeを活用してJSONからデータを取り出す方法

ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(jsonStr);
JsonNode firstFeatureNode = rootNode.get("Feature").get(0);

//座標を取得
String coordinates = firstFeatureNode.get("Geometry").get("Coordinates").asText();

//経度,緯度で配列化する
String[] coordinatesArray = coordinates.split(",");

座標が取得できたら、Modelクラスにセットし、htmlを介しjsへパラメータを送る準備をする

model.addAttribute("coordinatesArray",coordinatesArray);

これで座標は取得できました。

leafletを使って、座標から地図にピン留めを行う

htmlではthymeleafを使用。ModelクラスにセットしたcoordinatesListから値を取得できる。

<div class ="map" th:id="map" th:attr="data-latitude=${coordinatesList[1]},data-longitude=${coordinatesList[0]}" style="height: 30rem;"></div>

jsでattrで作成した属性(data-latitude,data-longitude)の値を取得する。
その値は座標なので、文字列からFloatに変換する。
座標をLeafLetのオブジェクトにセットしていく。

window.addEventListener("load", function() {
	
    var elements = document.querySelectorAll(".map");
    elements.forEach(function(e, index) {
        var latitude = e.getAttribute('data-latitude');
        var longitude = e.getAttribute('data-longitude');
        var shopName = '具志三丁目戸建';

		// 文字列から数値に変換
        var lat = parseFloat(latitude); 
        var lng = parseFloat(longitude); 
        var map = L.map(e.id).setView([lat, lng], 10);
        
        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: "© OpenStreetMap contributors"
        }).addTo(map);

        // マーカーを追加
        var marker = L.marker([lat, lng]).addTo(map);
        marker.bindPopup(shopName).openPopup(); 
    });
    alert('表示しました');
});

これでピン留めができるようになりました。

Discussion