Provides automatic context loading for new Claude Code sessions, documenting architecture, filters, sources, and conventions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.7 KiB
4.7 KiB
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) awrite_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ě
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
# 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
- Sreality
- Bezrealitky
- iDNES
- PSN + CityHome (paralelně)
- Bazoš
- Realingo (poslední — uživatelka ho nemá ráda)
- Merge + mapa
- Status generování
Konvence
- Commit messages v angličtině, PR popis v angličtině
- Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com
- 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