# /opt/docker/dev/service_finder/backend/app/workers/osm_scout.py import asyncio import json import httpx import hashlib import logging from urllib.parse import quote from sqlalchemy import select from app.database import AsyncSessionLocal from app.models.staged_data import ServiceStaging logger = logging.getLogger("Robot-OSM-Scout") class OSMScout: """ Robot: OSM Scout (V2) Feladata: Országos, ingyenes adatgyűjtés az OpenStreetMap hálózatából. """ HUNGARY_BBOX = "45.7,16.1,48.6,22.9" OVERPASS_URL = "http://overpass-api.de/api/interpreter?data=" @staticmethod def generate_fingerprint(name: str, city: str) -> str: raw = f"{str(name).lower()}|{str(city).lower()}" return hashlib.md5(raw.encode()).hexdigest() async def fetch_osm_data(self, query_part: str): query = f'[out:json][timeout:120];(node{query_part}({self.HUNGARY_BBOX});way{query_part}({self.HUNGARY_BBOX}););out center;' async with httpx.AsyncClient(timeout=150) as client: try: resp = await client.get(self.OVERPASS_URL + quote(query)) return resp.json().get('elements', []) if resp.status_code == 200 else [] except Exception as e: logger.error(f"❌ Overpass hiba: {e}") return [] async def run(self): logger.info("🛰️ OSM Scout ONLINE - Országos porszívózás indítása...") queries = ['["shop"~"car_repair|tyres"]', '["amenity"="car_wash"]'] all_elements = [] for q in queries: all_elements.extend(await self.fetch_osm_data(q)) async with AsyncSessionLocal() as db: added = 0 for node in all_elements: tags = node.get('tags', {}) if not tags.get('name'): continue name = tags.get('name', tags.get('operator', 'Ismeretlen')) city = tags.get('addr:city', 'Ismeretlen') f_print = self.generate_fingerprint(name, city) # Deduplikáció check stmt = select(ServiceStaging).where(ServiceStaging.fingerprint == f_print) if not (await db.execute(stmt)).scalar(): db.add(ServiceStaging( name=name, source="osm_scout_v2", fingerprint=f_print, city=city, full_address=f"{city}, {tags.get('addr:street', '')} {tags.get('addr:housenumber', '')}".strip(", "), status="pending", trust_score=20, raw_data=tags )) added += 1 await db.commit() logger.info(f"✅ OSM Scout végzett. {added} új potenciális szerviz a Stagingben.") if __name__ == "__main__": asyncio.run(OSMScout().run())