1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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()
|