gendesign/tradein-mvp/packages/scraper-kit/src/scraper_kit/price_brackets.py
bot-backend cf91ac6b24
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 52s
feat(tradein/scraper): per-city sweep capability для 5 городов области (schedules disabled)
B1: avito/cian/yandex city-sweep по городам Свердловской обл. (Н.Тагил/Каменск/Первоуральск/В.Пышма/Серов). Schedules засеяны DISABLED — rollout вручную по одному городу (proxy = 1 живой прокси).

- pipeline.py: CITY_ANCHORS (5) + get_city_anchors(slug) (None→EKB fallback).
- scheduler.py: sweep-jobs читают params.city → анкоры; wildcard-хендлеры *_city_sweep_* (source UNIQUE → per-city source, как deactivate_stale_*).
- geo.py: OBLAST66_BBOX + is_within_oblast66_bbox; avito/detail.py ingest-guard EKB→oblast66.
- price_brackets.py: 5 city-seed (reuse EKB). migration 179: 15 rows enabled=false, staggered, idempotent.
- +6 тестов. domclick (B2) не тронут.
2026-07-12 20:06:46 +03:00

44 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Общие seed price-brackets для exhaustive-скрапперов (avito/cian/yandex).
EKB-настроенные (анализ прод-распределения вторички ЕКБ). Структура city-dict —
готова под per-city (multi-city: Москва пик 15-40М, Тюмень — иные; multi-city —
отдельная фича, см. vault decision). Сейчас единственный город — ekaterinburg.
"""
# (lo, hi) рубли; hi=None — открытый верхний брекет (без потолка). Закрытые
# брекеты соприкасаются — вызывающий применяет hi-1 (эксклюзивный верх), дедуп
# по source_id страхует на стыках.
_EKB_SECONDARY: list[tuple[int, int | None]] = [
(0, 4_000_000),
(4_000_000, 5_000_000),
(5_000_000, 6_000_000),
(6_000_000, 7_000_000),
(7_000_000, 8_000_000),
(8_000_000, 10_000_000),
(10_000_000, 13_000_000),
(13_000_000, 17_000_000),
(17_000_000, 25_000_000),
(25_000_000, 250_000_000),
(250_000_000, None), # 250М+ открытый catch-all (без потолка)
]
CITY_PRICE_SEED_BRACKETS: dict[str, list[tuple[int, int | None]]] = {
"ekaterinburg": _EKB_SECONDARY,
# B1 oblast rollout (Свердловская область, region 66) — Н.Тагил/Каменск-Уральский/
# Первоуральск/В.Пышма/Серов вторичка дешевле ЕКБ (меньше 17-25М+ сегмента), но
# отдельного per-city анализа прод-распределения пока не делали (сами schedule'ы
# ship disabled — данных для брекетов ещё нет). Временно реюзаем EKB-брекеты как
# безопасный upper-bound-охват (get_price_seed_brackets и так фоллбэчит на
# ekaterinburg для незнакомых городов — эти entries делают выбор ЯВНЫМ, не implicit
# fallback, чтобы легче было найти и заменить, когда появится реальная статистика).
"nizhniy_tagil": _EKB_SECONDARY,
"kamensk_uralskiy": _EKB_SECONDARY,
"pervouralsk": _EKB_SECONDARY,
"verkhnyaya_pyshma": _EKB_SECONDARY,
"serov": _EKB_SECONDARY,
}
def get_price_seed_brackets(city: str = "ekaterinburg") -> list[tuple[int, int | None]]:
"""Seed price-brackets для города (fallback на ekaterinburg)."""
return CITY_PRICE_SEED_BRACKETS.get(city, _EKB_SECONDARY)