Osmium ist ein CLI-Tool für die Arbeit mit OSM-Daten (OpenStreetMap) und basiert auf der C-Bibliothek libosmium.
Search-Source extrahieren
wget https://download.geofabrik.de/europe/austria-latest.osm.pbf osmium tags-filter austria-latest.osm.pbf \ nwr/place \ nwr/amenity \ nwr/shop \ nwr/tourism \ nwr/leisure \ nwr/railway \ nwr/public_transport \ nwr/highway \ nwr/addr:* \ -o search-source.osm.pbf osmium export search-source.osm.pbf -o search-source.geojson
search.json bauen
import json INPUT = "search-source.geojson" OUTPUT = "search.json" def center_of_geometry(geom): t = geom.get("type") coords = geom.get("coordinates") if t == "Point": return coords[0], coords[1] if t == "LineString" and coords: mid = coords[len(coords) // 2] return mid[0], mid[1] if t == "Polygon" and coords and coords[0]: ring = coords[0] mid = ring[len(ring) // 2] return mid[0], mid[1] if t == "MultiPolygon" and coords and coords[0] and coords[0][0]: ring = coords[0][0] mid = ring[len(ring) // 2] return mid[0], mid[1] return None, None def norm(props, *keys): for k in keys: v = props.get(k) if v: return str(v).strip() return "" with open(INPUT, "r", encoding="utf-8") as f: geo = json.load(f) out = [] seen = set() for feat in geo.get("features", []): props = feat.get("properties", {}) geom = feat.get("geometry", {}) lng, lat = center_of_geometry(geom) if lng is None or lat is None: continue name = norm(props, "name:de", "name_de", "name") place = norm(props, "place") housenumber = norm(props, "addr:housenumber") street = norm(props, "addr:street") city = norm(props, "addr:city", "addr:place") postcode = norm(props, "addr:postcode") amenity = norm(props, "amenity") shop = norm(props, "shop") tourism = norm(props, "tourism") leisure = norm(props, "leisure") railway = norm(props, "railway") public_transport = norm(props, "public_transport") highway = norm(props, "highway") item = None if housenumber and street: item = { "t": "house", "name": f"{street} {housenumber}", "street": street, "housenumber": housenumber, "city": city, "postcode": postcode, "lat": round(lat, 6), "lng": round(lng, 6), } elif highway and name: item = { "t": "street", "name": name, "city": city, "postcode": postcode, "lat": round(lat, 6), "lng": round(lng, 6), } elif place and name: item = { "t": "place", "name": name, "place": place, "postcode": postcode, "lat": round(lat, 6), "lng": round(lng, 6), } elif name and (amenity or shop or tourism or leisure or railway or public_transport): item = { "t": "poi", "name": name, "class": amenity or shop or tourism or leisure or railway or public_transport, "lat": round(lat, 6), "lng": round(lng, 6), } if not item: continue key = (item["t"], item["name"], item["lat"], item["lng"]) if key in seen: continue seen.add(key) out.append(item) with open(OUTPUT, "w", encoding="utf-8") as f: json.dump(out, f, ensure_ascii=False, separators=(",", ":")) print(f"{len(out)} Einträge nach {OUTPUT} geschrieben")
Im Browser suchen
let SEARCH_INDEX = []; async function loadSearchIndex() { const res = await fetch("search.json"); SEARCH_INDEX = await res.json(); } function searchLocal(query) { const q = query.trim().toLowerCase(); if (!q) return []; return SEARCH_INDEX .filter(item => { const hay = [ item.name || "", item.street || "", item.city || "", item.postcode || "" ].join(" ").toLowerCase(); return hay.includes(q); }) .slice(0, 20); }