# Trade-In MVP — Roadmap «Максимум» > Решение 19.05 вечером: убираем привязку к срокам, делаем максимально хорошо. > План структурирован по архитектурным слоям, не по дням. Катимся сверху-вниз — > каждый следующий слой требует, чтобы предыдущий был стабилен. ## Видение продукта **Что есть у Брусники:** 4-стр PDF с медианой цен, диапазоном, аналогами и сравнением «их обмен vs самопродажа». Один white-label (Брусника). Один продукт. **Что мы делаем поверх:** 1. **Парсим больше источников** (6 vs ~5 у Брусники): Авито, Циан, Дом.Клик, Я.Недвижимость, Н1, Дом.РФ 2. **Кликабельные ссылки** на каждый аналог — Брусника не даёт 3. **Real-time freshness** — индикатор «обновлено N минут назад» на каждом источнике 4. **Объяснимый confidence** — `high (12 аналогов, разброс ±8%)` вместо «качество данных может быть не очень» 5. **POI окружение** — школы / метро / магазины с decay по расстоянию (переиспользуем код gendesign Site Finder) 6. **Тренд цен** — график за 6/24 мес. в этом районе 7. **Map view** — карта с точками аналогов + heatmap 8. **Multi-tenant white-label** — PRINZIP / Практика / любой бренд через query param 9. **JSON API + iframe widget** — для интеграции в чужие CRM 10. **Похожие сделки в том же доме** — точные совпадения если есть 11. **AI narrative summary** — короткое описание квартиры от LLM 12. **Прогноз срока продажи** — median days_on_market по выборке 13. **Score breakdown explainability** — почему именно эта цена (как Site Finder) 14. **Photo upload** на cover PDF 15. **Shareable URL** + QR-код в PDF --- ## Слой 1 — Core data layer (фундамент) Без него ничего не работает. Каждый последующий слой строится поверх. ### 1.1 Postgres schema - `listings` — объявления (id, source, source_url, lat, lon, address, rooms, area, floor, total_floors, year_built, house_type, repair_state, price, price_per_m2, photo_urls jsonb, listing_date, scraped_at, dedup_hash, raw_payload jsonb, geom GEOMETRY(Point, 4326)) - `deals` — фактические сделки (тот же набор + deal_date, source = 'rosreestr' пока) - `geocode_cache` — address → lat/lon кэш (избегаем повторных Yandex hits) - `audit_log` — каждый POST /estimate (ip, user_agent, input, estimate_id, ts) - `house_metadata` — кэш данных ЕКБ Геопортала по координатам/кадастру (этажи, год, материал, кол-во квартир) - Индексы: GIST на geom, btree на (rooms, scraped_at), unique на dedup_hash ### 1.2 Geocoder + Suggest - `app/services/geocoder.py` — Yandex Geocoder через httpx + кэш в `geocode_cache` - `app/services/suggest.py` — Yandex Suggest для frontend autocomplete (proxy через backend, не светим API key в браузере) - Fallback к Nominatim если Яндекс упал / лимит ### 1.3 Scraper framework - `app/services/scrapers/base.py` — общий BaseScraper - Retry через `tenacity` (3 попытки, exp backoff) - Rotation: пул из 5-10 User-Agent + Accept-Language - Sleep 5-10 sec между запросами (без бана) - Поддержка Playwright если scrapy не справляется (Циан иногда JS-render требует) - Дедупликация: `dedup_hash = sha256(source + source_url + price)` уникальный - Каждый scraper возвращает list[ScrapedLot] — единая Pydantic схема --- ## Слой 2 — Парсеры источников ### 2.1 Авито (приоритет 1 — стартуем с него) - URL: `/ekaterinburg/kvartiry/prodam?radius=N&geoCoords=lat,lon&list_view=1` - Парс HTML через `selectolax` (быстрее BeautifulSoup) - Поля: address, rooms, area, floor/total_floors, price, listing_date, photo, deeplink - Edge case: «частный риэлтор» vs «агентство» — фильтруем спам ### 2.2 Циан ✅ ДЕПЛОЕН - URL: `https://ekaterinburg.cian.ru/cat.php?...` - ВАЖНО: Циан банит httpx по TLS fingerprint → `curl_cffi(impersonate="chrome120")` - 2025+ верстка БЕЗ `__NEXT_DATA__` — парсим DOM по `data-mark` атрибутам: `OfferTitle`, `MainPrice`, `Description`; адрес из множественных `data-name="GeoLabel"` - Multi-room scrape: `fetch_around_multi_room()` по rooms=1/2/3/4 → ~108 unique lots - Cron каждый час: `45 * * * * /opt/tradein-mvp/deploy/cron-scrape.sh cian fast` ### 2.3 Росреестр сделки - Дамп из prod gendesign `rosreestr_deals` (6.83M строк, partitioned по кварталам) - SSH туннель → `pg_dump --table rosreestr_deals --where "region_code = 66"` → restore локально - Регулярный refresh: weekly Celery task ### 2.4 Дом.Клик - API: `https://api.domclick.ru/...` (публичный, без auth, JSON) - Поля: те же + ипотечные опции (мы пока игнорим) ### 2.5 Я.Недвижимость ✅ ДЕПЛОЕН - URL: `https://realty.yandex.ru/ekaterinburg/kupit/kvartira/?rgid=240970&offerType=SELL` - State в `