From 59ef3274b685b9b51f99baecd38f0864bfd1ff3d Mon Sep 17 00:00:00 2001 From: Marie Michalova Date: Fri, 6 Mar 2026 09:58:01 +0100 Subject: [PATCH] Add CLAUDE.md project documentation for session context Provides automatic context loading for new Claude Code sessions, documenting architecture, filters, sources, and conventions. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..8199f48 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,124 @@ +# Maru hledá byt + +Projekt pro hledání bytů v Praze. Scrapuje inzeráty ze 7 realitních portálů, filtruje, deduplikuje a generuje interaktivní mapu. + +**Jazyk komunikace:** Čeština (uživatelka Marie). Kód a komentáře v kódu jsou mix CZ/EN. + +## Architektura + +``` +run_all.sh (orchestrátor) + ├─ scrape_and_map.py → byty_sreality.json (Sreality API) + ├─ scrape_bezrealitky.py → byty_bezrealitky.json (HTML Apollo cache) + ├─ scrape_idnes.py → byty_idnes.json (HTML regex) + ├─ scrape_psn.py } → byty_psn.json (React API + curl) + ├─ scrape_cityhome.py } → byty_cityhome.json (HTML tabulky) + ├─ scrape_bazos.py → byty_bazos.json (HTML regex) + └─ scrape_realingo.py → byty_realingo.json (Next.js __NEXT_DATA__) + ↓ + merge_and_map.py + ├─ byty_merged.json (deduplikovaná data) + └─ mapa_bytu.html (Leaflet.js mapa) + ↓ + generate_status.py → status.json + scraper_history.json + ↓ + server.py (port 8080) → servíruje mapu + status page + ratings API +``` + +## Filtry (společné všem scraperům) + +| Parametr | Hodnota | Poznámka | +|----------|---------|----------| +| Max cena | 13.5M Kč (Sreality/Realingo/Bezrealitky/iDNES), 14M Kč (PSN/CityHome/Bazoš) | Rozdíl je záměrný | +| Min plocha | 69 m² | | +| Min patro | 2. NP | 2. NP se na mapě označí varováním | +| Dispozice | 3+kk, 3+1, 4+kk, 4+1, 5+kk, 5+1, 6+ | | +| Region | Praha | | +| Vyloučit | panelové domy, sídliště | regex v popisu/polích | + +## Klíčové soubory + +- **scrape_and_map.py** — Sreality scraper + `generate_map()` funkce (sdílená, generuje HTML mapu) +- **merge_and_map.py** — sloučí 7 JSON zdrojů, deduplikuje (klíč: ulice + cena + plocha), volá `generate_map()` +- **scraper_stats.py** — utility: `validate_listing()` (validace povinných polí + GPS bounds) a `write_stats()` +- **generate_status.py** — generuje status.json a scraper_history.json z výstupů scraperů +- **server.py** — HTTP server (port 8080), endpointy: `/mapa_bytu.html`, `/scrapers-status`, `/api/ratings`, `/api/status` +- **run_all.sh** — orchestrátor, spouští scrapery postupně (PSN+CityHome paralelně), pak merge + status + +## Mapa (mapa_bytu.html) + +- Leaflet.js + CARTO tiles +- Barvy markerů podle ceny/m² (modrá < 110k → červená > 165k, šedá = neuvedeno) +- PSN/CityHome = srdíčkové markery (❤️) +- Nové inzeráty (≤ 1 den) = žlutý badge "NEW" +- Zamítnuté = zprůhledněné + 🚫 SVG overlay +- Oblíbené = hvězdička (⭐) +- Filtry: patro, max cena (input, default 13.5M, max 14M), datum přidání, skrýt zamítnuté, klik na cenový pás +- Ratings uložené v localStorage + sync na server `/api/ratings` + +## Barvy zdrojů na mapě + +```python +source_colors = { + "sreality": "#1976D2", # modrá + "realingo": "#00897B", # teal + "bezrealitky": "#E91E63", # růžová + "idnes": "#FF6F00", # oranžová + "psn": "#D32F2F", # červená + "cityhome": "#D32F2F", # červená + "bazos": "#7B1FA2", # fialová +} +``` + +## Deduplikace (merge_and_map.py) + +- Klíč: `normalize_street(locality) + price + area` +- Normalizace ulice: první část před čárkou, lowercase, odstranění diakritiky, jen alfanumerické znaky +- PSN a CityHome mají prioritu (načtou se první) + +## Vývoj + +- **Git remote:** `https://gitea.home.hrajfrisbee.cz/littlemeat/maru-hleda-byt.git` +- **Gitea API token:** uložen v `.claude/settings.local.json` +- **Python 3.9+** kompatibilita (`from __future__ import annotations`) +- **Žádné pip závislosti** — jen stdlib (urllib, json, re, logging, pathlib, subprocess) +- **Docker:** `build/Dockerfile` (python:3.13-alpine), cron každé 4 hodiny +- Generované soubory (`byty_*.json`, `mapa_bytu.html`, `*.log`) jsou v `.gitignore` + +## Typické úlohy + +```bash +# Rychlý test scraperu +python3 scrape_bazos.py --max-pages 1 --max-properties 5 --log-level DEBUG + +# Lokální validace (všechny scrapery s limity) +make validation-local + +# Vygenerovat mapu z existujících dat +python3 merge_and_map.py + +# Spustit server +python3 server.py # nebo: make serve + +# Plný scrape +./run_all.sh +``` + +## Pořadí scraperů v run_all.sh + +1. Sreality +2. Bezrealitky +3. iDNES +4. PSN + CityHome (paralelně) +5. Bazoš +6. Realingo (poslední — uživatelka ho nemá ráda) +7. Merge + mapa +8. Status generování + +## Konvence + +- Commit messages v angličtině, PR popis v angličtině +- Co-Authored-By: Claude Opus 4.6 +- PRy přes Gitea API (viz create_pr.sh pattern v historii) +- Nové scrapery kopírují vzor z `scrape_bezrealitky.py` +- Každý scraper má argparse s `--max-pages`, `--max-properties`, `--log-level`