lekss361
879f761214
feat(tradein): avito_houses.py — Houses Catalog parser (state + reviews + history + recs)
...
Stage 2c of AvitoScraper_v2.
- fetch_house_catalog(house_url) — async HTTP via curl_cffi (chrome120)
- parse_houses_state(state, house_url) — pure parser (testable без сети)
- 10-widget JSON state structure (housePage, reviews, miniSerp, housePlacementHistory, recommendations)
- Dataclasses:
* HouseInfo (28 fields: identity, geo, expandParams flatten, developer, rating, map_pins, raw_characteristics)
* HouseReview (textSections split: main/pros/cons; ru date parse)
* PlacementHistoryItem (removed_date ALWAYS None — widget не отдаёт; точная дата только в IMV API)
* SellerInfo (ext_seller_id из URL last segment, без logos)
* MiniSerpListing (active listings в доме + metro + seller)
* RecommendationItem (lightweight: title/price_text/address/url/image)
* HouseCatalogEnrichment (orchestrator dataclass)
- Save flow (5 ops):
* _upsert_house_with_url → houses (UNIQUE source='avito', ext_house_id) + raw_characteristics jsonb
* save_house_reviews → house_reviews (UNIQUE source, ext_review_id), без images
* save_sellers → sellers (UNIQUE source, ext_seller_id), без logos
* link_listings_to_seller → UPDATE listings.seller_id_fk by source_id match
* save_placement_history → source='avito_widget', removed_date=NULL
- pytest offline smoke: 18 tests, 5 widget types, 25+ field assertions
- Recommendations save skipped — Stage 3 решит
2026-05-23 15:27:22 +03:00
lekss361
7f03a5b634
feat(tradein): cian_state_parser shared utility + ScrapedLot Cian fields
...
- Add cian_state_parser.py: regex-based extractor for window._cianConfig push() entries,
supports direct JSON, JSON.parse() escaped form, and optional demjson3 fallback
- Extend ScrapedLot in base.py with 13 Cian-specific fields (living_area_m2,
bedrooms_count, balconies_count, loggias_count, description_minhash,
cadastral_number, building_cadastral_number, phones, is_homeowner, is_pro_seller,
bargain_allowed, sale_type, metro_stations)
- Add tests/test_cian_state_parser.py with 4 unit tests covering all parse strategies
2026-05-23 15:24:50 +03:00
7cdde30b13
feat(tradein): avito_detail.py — detail page parser (30+ fields incl. domoteka) ( #443 )
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 38s
Deploy Trade-In / deploy (push) Successful in 17s
2026-05-23 12:17:15 +00:00
6a2f734356
feat(tradein): avito_imv.py — Avito IMV evaluation API client (2 requests) ( #444 )
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been cancelled
2026-05-23 12:16:47 +00:00
47f4cc7d58
refactor(tradein): avito search — remove jitter (C-5) + mobile API dead code + parse houseLinks ( #441 )
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 39s
Deploy Trade-In / deploy (push) Successful in 18s
2026-05-23 11:55:18 +00:00
1d788b27d0
fix(tradein): Avito-парсер тащит фото и реальный адрес из DOM-карточек
...
DOM-путь (_dom_card_to_lot) — основной для Avito: mobile API отдаёт
бан, формат __initialState__ устарел, так что почти все объявления
идут через него. Но он не извлекал фото вообще, а адрес брал мёртвым
селектором [class*="geo-address"] — поэтому объявления Avito оставались
без фото (серый блок в Сводке) и с заглушкой «Екатеринбург (Avito)».
Теперь:
- фото — из <img itemprop="image"> карточки-слайдера (до 5 шт);
- адрес — первый <p> внутри data-marker="item-location" (улица + дом).
Селекторы проверены на живой выдаче Avito.
2026-05-22 13:49:09 +05:00
TradeIn Deploy
7cc8d8370d
feat(tradein): пагинация Циан/N1 3→8 страниц — плотность данных
...
После перехода на реальные координаты стало видно что данных тонко.
8 страниц × 4 комнаты ≈ 900+ лотов на источник вместо ~300.
2026-05-21 14:34:29 +03:00
TradeIn Deploy
d2a740779d
fix(tradein): реальные координаты Cian/N1 через геокодинг (был баг 0 аналогов)
...
Cian/N1 ставили anchor+jitter координаты — фейковые, вокруг центрального
якоря. Для адресов вдали от центра ST_DWithin не находил аналоги → 0.
Теперь Cian/N1 оставляют lat/lon=None, geocode-missing проставляет реальные
координаты по адресу (geom пересчитывается триггером). cron вызывает
geocode-missing после скрейпа. Адрес чистится от суффикса · р-н.
2026-05-21 13:14:33 +03:00
TradeIn Deploy
f7b820984b
feat(tradein): радиус 1000м + пагинация Циан/N1
...
DEFAULT_RADIUS_M 800→1000 (по встрече Птицы: локация до 800-1000м).
Cian/N1 multi-room теперь обходят 3 страницы выдачи → ~2-3x больше лотов.
2026-05-21 11:59:16 +03:00
TradeIn Deploy
42a0c31f27
feat(tradein): N1.ru scraper + cron для 4 источников
...
Добавлен 4-й источник N1.ru (ekaterinburg.n1.ru) — региональный портал,
хорошо представлен на Урале. DOM-парсинг карточек data-test=offers-list-item
через curl_cffi. Multi-room сегментация 1/2/3/4к.
cron-scrape.sh переписан под прод: запрос к backend через docker exec
(без публичного admin/scrape), все 4 источника (avito/cian/yandex/n1).
2026-05-21 11:44:32 +03:00
lekss361
02267d0306
feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in)
...
- FastAPI backend: PostGIS estimator + 3 scrapers (Avito/Cian/Yandex)
- Next.js 15 frontend: tradein.html mockup design, basePath=/trade-in
- WeasyPrint PDF (Брусника-style 4-page report)
- Address autocomplete с typo-tolerance + 6 EKB presets
- Изолированный docker stack gendesign-tradein (отдельная postgres БД)
- Caddy inline routes: gendsgn.ru/trade-in/* и /trade-in/api/v1/*
- Forgejo Actions: .forgejo/workflows/deploy-tradein.yml (shell-based GHCR login)
- Триггер только по paths: tradein-mvp/** (не пересекается с deploy.yml)
- Образы: ghcr.io/lekss361/gendesign-tradein-{backend,frontend}:latest
Первый запуск на сервере (вручную, один раз):
- создать /opt/gendesign/tradein-mvp/.env.runtime (postgres pwd, contact email)
- docker network create gendesign_shared (если нет)
- docker compose -p gendesign-tradein up -d
- docker compose -p gendesign exec caddy caddy reload
2026-05-21 00:25:39 +03:00