forked from Bestinhop23/WHERES-DA-CRAIC
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeocode_events.py
More file actions
98 lines (80 loc) · 2.99 KB
/
Copy pathgeocode_events.py
File metadata and controls
98 lines (80 loc) · 2.99 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env python3
"""Geocode events in events_v1.json using Nominatim API."""
import json
import time
import urllib.request
import urllib.parse
EVENTS_FILE = "/Users/helios/WHERES-DA-CRAIC/events_v1.json"
NOMINATIM_URL = "https://nominatim.openstreetmap.org/search"
HEADERS = {"User-Agent": "WheresDaCraic/1.0 (geocoding events for wheres-da-craic app)"}
def nominatim_search(query: str) -> tuple[float, float] | None:
"""Query Nominatim and return (lat, lon) or None if no result."""
params = urllib.parse.urlencode({"q": query, "format": "json", "limit": "1"})
url = f"{NOMINATIM_URL}?{params}"
req = urllib.request.Request(url, headers=HEADERS)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
data = json.loads(resp.read().decode())
if data:
return float(data[0]["lat"]), float(data[0]["lon"])
except Exception as e:
print(f" [error] {query!r}: {e}")
return None
def geocode_event(event: dict) -> tuple[float | None, float | None]:
"""Try three strategies to geocode an event. Returns (lat, lon) or (None, None)."""
address = event.get("address", "").strip()
venue = event.get("venue", "").strip()
county = event.get("county", "").strip()
# Strategy 1: full address
if address:
print(f" Trying address: {address!r}")
result = nominatim_search(address)
if result:
return result
time.sleep(1)
# Strategy 2: venue + ", Ireland"
if venue:
query = f"{venue}, Ireland"
print(f" Trying venue: {query!r}")
result = nominatim_search(query)
if result:
return result
time.sleep(1)
# Strategy 3: county + ", Ireland"
if county:
query = f"{county}, Ireland"
print(f" Trying county: {query!r}")
result = nominatim_search(query)
if result:
return result
time.sleep(1)
return None, None
def main():
with open(EVENTS_FILE, "r") as f:
data = json.load(f)
events = data["events"]
total = len(events)
geocoded = 0
null_count = 0
for i, event in enumerate(events):
name = event.get("name", f"event {i}")
print(f"\n[{i+1}/{total}] {name}")
lat, lon = geocode_event(event)
event["lat"] = lat
event["lon"] = lon
if lat is not None and lon is not None:
geocoded += 1
print(f" -> lat={lat}, lon={lon}")
else:
null_count += 1
print(f" -> null (could not geocode)")
# Rate limit: 1 second between requests (already sleeping inside geocode_event,
# but add a gap after success too so we never exceed 1 req/sec)
time.sleep(1)
with open(EVENTS_FILE, "w") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f"\n{'='*60}")
print(f"Done. {geocoded}/{total} events geocoded successfully.")
print(f"{null_count}/{total} events got null coordinates.")
if __name__ == "__main__":
main()