Регулярный сбор ДомКлика по Москве и области (#3545)
All checks were successful
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 3m51s
Deploy Trade-In / build-backend (push) Successful in 1m49s
Deploy Trade-In / deploy (push) Successful in 7m53s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 1m43s
All checks were successful
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 3m51s
Deploy Trade-In / build-backend (push) Successful in 1m49s
Deploy Trade-In / deploy (push) Successful in 7m53s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 1m43s
This commit is contained in:
parent
8ebd63780f
commit
1452e63eec
4 changed files with 96 additions and 2 deletions
|
|
@ -1008,6 +1008,12 @@ def build_product_handlers(ctx: SchedulerContext) -> dict[str, Handler]:
|
|||
),
|
||||
# Override kit-native (#3264) — инъекция куки сессии, см. докстринг job'а выше.
|
||||
"domclick_city_sweep": Handler(_job_domclick_city_sweep, "domclick_city_sweep"),
|
||||
# Вне ЕКБ каждый регион получает СВОЙ source ("domclick_city_sweep_moskva"),
|
||||
# потому что scrape_schedules.source UNIQUE. Wildcard обязан стоять и здесь,
|
||||
# а не только в _default_kit_handlers: kit-native тело ходит БЕЗ кук сессии,
|
||||
# и московская строка молча резолвилась бы на версию без инъекции (#3264),
|
||||
# то есть на ту, что упирается в QRATOR. Ключ продукта перекрывает kit-native.
|
||||
"domclick_city_sweep_*": Handler(_job_domclick_city_sweep, "domclick_city_sweep_*"),
|
||||
"cadastral_geo_match": Handler(_job_cadastral_geo_match, "cadastral_geo_match"),
|
||||
"osm_poi_ekb_refresh": Handler(_job_osm_poi_ekb_refresh, "osm_poi_ekb_refresh"),
|
||||
"dtp_stat_refresh": Handler(_job_dtp_stat_refresh, "dtp_stat_refresh"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
-- 306_scrape_schedules_seed_domclick_msk.sql
|
||||
-- Регулярный сбор ДомКлика по Москве (77) и Московской области (50).
|
||||
--
|
||||
-- Apply after: 305_scrape_schedules_seed_msk_city_sweeps.sql
|
||||
--
|
||||
-- WHY:
|
||||
-- Миграция 305 завела регулярный сбор 77/50 для avito / cian / yandex и прямо
|
||||
-- отложила ДомКлик: "у него нет wildcard-хендлера, а единственная возможная
|
||||
-- строка source='domclick_city_sweep' занята Екатеринбургом. Нужна правка кода".
|
||||
-- Правка сделана в этом же PR — "domclick_city_sweep_*" добавлен в
|
||||
-- _default_kit_handlers (scraper-kit) И в build_product_handlers (app-side
|
||||
-- override с инъекцией куки Sber ID, #3264). Эта миграция — вторая половина.
|
||||
--
|
||||
-- Цена вопроса: ДомКлик даёт ≈23% корпуса обоих регионов. Без него свежий срез
|
||||
-- 77/50 теряет почти четверть массы, а вместе с ней — часть домов, по которым
|
||||
-- вообще существуют аналоги.
|
||||
--
|
||||
-- Гео-скоуп задаётся ТОЛЬКО region_code: профиль региона
|
||||
-- (providers/domclick/serp.py DOMCLICK_GEO_PROFILES) несёт address GUID,
|
||||
-- страницу прогрева QRATOR, bbox гарда и имя города. Профили 77 и 50 заведены и
|
||||
-- проверены живыми запросами 12-15.09.2026 (#3533). city_id здесь НЕ задаётся
|
||||
-- намеренно: он vestigial — run_domclick_city_sweep штампует город из профиля,
|
||||
-- а не из city_id (pipeline.py, комментарий у save_listings). Неизвестный
|
||||
-- region_code роняет прогон ДО первого запроса, тихого отката на ЕКБ нет.
|
||||
--
|
||||
-- pages_per_anchor=100 — как у ЕКБ-строки: ДомКлик citywide, anchor-loop у него
|
||||
-- отсутствует (fetch_around → NotImplementedError), "pages" здесь означает
|
||||
-- глубину пагинации на комнатный бакет, а не число якорей. Москва отдаёт ≈23 690
|
||||
-- лотов вторички, то есть глубину надо брать полную, а не свипную.
|
||||
--
|
||||
-- Окна 0-3 и 3-6 UTC: 305 занял 16-23, ЕКБ-домклик сидит в 3-6. Ставим Москву в
|
||||
-- 0-3 (пусто), область — в 3-6 рядом с ЕКБ; прогоны всё равно сериализуются
|
||||
-- планировщиком, окно лишь ограничивает старт.
|
||||
--
|
||||
-- interval_days=3 — как у остальных строк 305: корпус живёт 14 суток
|
||||
-- (LISTINGS_FRESH_DAYS), трёхсуточный такт даёт четырёхкратный запас на
|
||||
-- пропуски из-за QRATOR-банов.
|
||||
--
|
||||
-- ВКЛЮЧЕНЫ СРАЗУ (enabled=true) по той же причине, что и 305: регионы уходят
|
||||
-- тестировщикам, корпус истекает.
|
||||
--
|
||||
-- ИДЕМПОТЕНТНОСТЬ: ON CONFLICT (source) DO NOTHING — повторный прогон no-op и не
|
||||
-- сбрасывает enabled, если строку потом выключили вручную.
|
||||
|
||||
BEGIN;
|
||||
|
||||
SET LOCAL lock_timeout = '5s';
|
||||
|
||||
INSERT INTO scrape_schedules (source, enabled, window_start_hour, window_end_hour, default_params)
|
||||
VALUES
|
||||
('domclick_city_sweep_moskva', true, 0, 3,
|
||||
'{"region_code": 77, "pages_per_anchor": 100, "interval_days": 3,
|
||||
"request_delay_sec": 6}'::jsonb),
|
||||
('domclick_city_sweep_moskovskaya_oblast', true, 3, 6,
|
||||
'{"region_code": 50, "pages_per_anchor": 100, "interval_days": 3,
|
||||
"request_delay_sec": 6}'::jsonb)
|
||||
ON CONFLICT (source) DO NOTHING;
|
||||
|
||||
COMMIT;
|
||||
|
|
@ -108,6 +108,7 @@ _KIT_NATIVE_SOURCES = {
|
|||
"cian_city_sweep_*",
|
||||
"cian_full_load",
|
||||
"domclick_city_sweep",
|
||||
"domclick_city_sweep_*",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -180,9 +181,11 @@ def test_real_build_product_handlers_covers_all_scheduled_sources() -> None:
|
|||
|
||||
|
||||
def test_kit_native_handler_set() -> None:
|
||||
"""Ровно 11 kit-native sweep-обработчиков зарегистрированы встроенно (8 + 3 oblast
|
||||
"""Ровно 12 kit-native sweep-обработчиков зарегистрированы встроенно (8 + 4 wildcard).
|
||||
|
||||
"*_city_sweep_*" wildcard, #179).
|
||||
"*_city_sweep_*" — per-city/per-region source'ы вне ЕКБ: avito/cian/yandex завела
|
||||
oblast B1 rollout (region 66, #179), domclick — регулярный сбор 77/50 (миграция 306),
|
||||
у него суффикс несёт регион, а не город.
|
||||
"""
|
||||
registry = build_registry()
|
||||
assert set(registry) == _KIT_NATIVE_SOURCES
|
||||
|
|
@ -190,6 +193,31 @@ def test_kit_native_handler_set() -> None:
|
|||
assert resolve_handler(src, registry).log_name == src
|
||||
|
||||
|
||||
def test_domclick_region_wildcard_resolves_to_product_handler() -> None:
|
||||
"""'domclick_city_sweep_moskva' резолвится на ПРОДУКТОВЫЙ handler, не на kit-native.
|
||||
|
||||
Развилка не косметическая: kit-native тело ходит на BFF без кук сессии Sber ID, и
|
||||
московская строка, севшая на него, упёрлась бы в QRATOR ровно так, как было до #3264.
|
||||
Продуктовый ключ обязан перекрывать kit-native и на wildcard, а не только на точном
|
||||
'domclick_city_sweep' — иначе перекрытие есть у ЕКБ и молча отсутствует у регионов.
|
||||
"""
|
||||
from app.services.product_handlers import (
|
||||
_job_domclick_city_sweep as product_job,
|
||||
)
|
||||
from app.services.product_handlers import build_product_handlers
|
||||
|
||||
# ctx=None безопасен — job'ы его не замыкают при сборке dict (см. тест выше).
|
||||
registry = build_registry(build_product_handlers(ctx=None)) # type: ignore[arg-type]
|
||||
for src in (
|
||||
"domclick_city_sweep",
|
||||
"domclick_city_sweep_moskva",
|
||||
"domclick_city_sweep_moskovskaya_oblast",
|
||||
):
|
||||
handler = resolve_handler(src, registry)
|
||||
assert handler is not None, src
|
||||
assert handler.job is product_job, src
|
||||
|
||||
|
||||
def test_unknown_source_resolves_none() -> None:
|
||||
registry, _ = _build_recording_registry()
|
||||
assert resolve_handler("totally_unknown_source", registry) is None
|
||||
|
|
|
|||
|
|
@ -1296,6 +1296,7 @@ def _default_kit_handlers() -> dict[str, Handler]:
|
|||
"cian_city_sweep_*": Handler(_job_cian_city_sweep, "cian_city_sweep_*"),
|
||||
"cian_full_load": Handler(_job_cian_full_load, "cian_full_load"),
|
||||
"domclick_city_sweep": Handler(_job_domclick_city_sweep, "domclick_city_sweep"),
|
||||
"domclick_city_sweep_*": Handler(_job_domclick_city_sweep, "domclick_city_sweep_*"),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue