From a71727538f65ab4f10f5239550be82590f9d47d1 Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Sat, 24 Oct 2026 12:29:24 +0900 Subject: parks: 公園一覧と地図、公共施設の情報を更新 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 近隣公園のクリックを市内公園と同じ挙動にし、Googleマップを公園名で開く - 公共施設のトイレを○にし、ルネこだいらを追加 - 未取得だった施設の座標を追加し、再ジオコーディング時の上書きを防止 - 手入力ポリゴン、近隣公園、PWA、ライセンス表示を追加 --- scripts/geocode-facilities.py | 86 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 scripts/geocode-facilities.py (limited to 'scripts/geocode-facilities.py') diff --git a/scripts/geocode-facilities.py b/scripts/geocode-facilities.py new file mode 100644 index 0000000..12c727c --- /dev/null +++ b/scripts/geocode-facilities.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""小平市の公共施設JSONに緯度・経度を付与する(Nominatim)。 + +使い方: + py -X utf8 scripts/geocode-facilities.py + +- `src/data/kodaira-facilities.json` の各施設に lat / lon / geocode を追加する。 +- 住所で見つからない場合は「小平市 + 施設名」で再試行する。 +- 見つからない場合は lat / lon を null にし、note に理由を追記する。 +- Nominatimの利用ポリシーに従い、1リクエストあたり約1.1秒待つ。 +""" +import json +import time +import urllib.parse +import urllib.request + +PATH = "src/data/kodaira-facilities.json" +UA = "yasutakeyohei.com facilities geocoder (park list)" + +# 住所・名称検索では正しい位置にならない施設。手動の座標を優先する。 +# 値は ((緯度, 経度), geocodeラベル)。 +MANUAL = { + "小平市役所(本庁)": ((35.7279025, 139.4774885), "手動補正"), + "西部出張所": ((35.735038, 139.461827), "小川西町図書館と同じ建物として補正"), + "小川分室": ((35.72604, 139.459319), "小川公民館と同じ建物として補正"), + "東部出張所": ((35.7279272, 139.5140803), "東部市民センターと同じ建物として補正"), + "喜平図書館": ((35.7173213, 139.4908793), "名称"), +} + + +def geocode(query): + url = ( + "https://nominatim.openstreetmap.org/search?format=jsonv2&limit=1&countrycodes=jp&q=" + + urllib.parse.quote(query) + ) + req = urllib.request.Request(url, headers={"User-Agent": UA}) + with urllib.request.urlopen(req, timeout=30) as r: + data = json.loads(r.read().decode("utf-8")) + if not data: + return None + return float(data[0]["lat"]), float(data[0]["lon"]) + + +def main(): + data = json.load(open(PATH, encoding="utf-8")) + for i, f in enumerate(data, 1): + name = f.get("name", "") + address = f.get("address", "") + if name in MANUAL: + (lat, lon), label = MANUAL[name] + f["lat"], f["lon"] = lat, lon + f["geocode"] = label + f["note"] = str(f.get("note", "")).replace("地図の位置は未取得。", "").strip() + print(f"{i}/{len(data)} {name}: {lat:.6f},{lon:.6f} ({label})") + continue + found = None + source = "" + if address: + found = geocode("東京都" + address) + source = "住所" + if not found and name: + time.sleep(1.1) + found = geocode("小平市" + name) + source = "名称" + if found and found[0] is not None: + f["lat"], f["lon"] = found + f["geocode"] = source + f["note"] = str(f.get("note", "")).replace("地図の位置は未取得。", "").strip() + print(f"{i}/{len(data)} {name}: {found[0]:.6f},{found[1]:.6f} ({source})") + else: + f["lat"], f["lon"] = None, None + f["geocode"] = "" + note = str(f.get("note", "")).strip() + if "地図の位置は未取得。" not in note: + f["note"] = (note + " " if note else "") + "地図の位置は未取得。" + print(f"{i}/{len(data)} {name}: NOT FOUND") + time.sleep(1.1) + with open(PATH, "w", encoding="utf-8") as fh: + json.dump(data, fh, ensure_ascii=False, indent=2) + fh.write("\n") + ok = sum(1 for f in data if f.get("lat") is not None) + print(f"geocoded {ok} / {len(data)} -> {PATH}") + + +if __name__ == "__main__": + main() -- cgit v1.3.1