tradein: вернуть domclick_detail_backfill после починки — выключена при 0 обогащений на 491 попытку #2636

Closed
opened 2026-08-02 14:13:11 +00:00 by lekss361 · 2 comments
Owner

Задача-напоминание, чтобы выключенная джоба не осталась выключенной навсегда. Заведена по замечанию ревью PR #2633: в миграции есть комментарий «до починки», но комментарий в SQL никто не перечитывает.

Что выключено и почему

Миграция 206 (206_scrape_schedules_cut_wasteful_load.sql) поставила enabled = false для domclick_detail_backfill.

Замер за 30 дней:

attempted = 491
enriched  = 0        ← ни одного успешного обогащения
failed    = 431
blocked   = 60

Ноль результата при 100% провале, причём включая прогоны через выделенный резидентный прокси (asocks-residential-1, affinity domclick) — то есть дело не в качестве IP.

Выключение не теряет данных: выхлоп и так был нулевой. Зато снимает 60 явных блокировок за месяц, то есть прямые удары по репутации выделенного узла Домклика — единственного, который сейчас стабильно здоров.

Что выяснить перед возвратом

  1. Почему 431 провал. Это ошибки парсинга, таймауты, смена вёрстки или блокировка? В счётчиках failed и blocked разведены, значит различие уже фиксируется — надо посмотреть тексты ошибок в логах.
  2. Не тот же ли это класс, что #2625 — молчаливый блок, засчитываемый как обычный сбой. У Домклика детект бана есть (domclick_exceptions.py), в отличие от Циана и Яндекса, но 60 blocked против 431 failed наводит на мысль, что распознаётся не всё.
  3. Нужна ли джоба вообще. Домклик даёт 6501 активное объявление, и они собираются городской развёрткой. Что именно добавляет детальная догрузка и насколько это влияет на оценку — если немного, возвращать не обязательно.

Как вернуть

UPDATE scrape_schedules SET enabled = true WHERE source = 'domclick_detail_backfill';

Отдельной миграцией, после того как причина провалов устранена и проверена хотя бы одним успешным прогоном вручную.

Прочее из того же ревью (мелочи в комментариях миграции 206)

Две формулировки слегка преувеличены, стоит поправить при ближайшем касании файла:

  • :89 — «rows_inserted=0 во ВСЕХ 30 прогонах» для yandex_newbuilding_sweep: на деле в первой трети окна было 11 ненулевых, а подряд нулевые — последние 17 дней. Решение о недельном такте от этого не меняется.
  • :29 — «20/30 banned мгновенно»: один из этих двадцати (прогон 693) успел выдать 108 вставок и 2792 обновления до бана.

Связано: #2633, #2613 (мёртвые прокси), #2625 (молчаливые блоки).

Задача-напоминание, чтобы выключенная джоба не осталась выключенной навсегда. Заведена по замечанию ревью PR #2633: в миграции есть комментарий «до починки», но комментарий в SQL никто не перечитывает. ## Что выключено и почему Миграция 206 (`206_scrape_schedules_cut_wasteful_load.sql`) поставила `enabled = false` для `domclick_detail_backfill`. Замер за 30 дней: ``` attempted = 491 enriched = 0 ← ни одного успешного обогащения failed = 431 blocked = 60 ``` Ноль результата при 100% провале, причём **включая прогоны через выделенный резидентный прокси** (`asocks-residential-1`, affinity `domclick`) — то есть дело не в качестве IP. Выключение не теряет данных: выхлоп и так был нулевой. Зато снимает 60 явных блокировок за месяц, то есть прямые удары по репутации выделенного узла Домклика — единственного, который сейчас стабильно здоров. ## Что выяснить перед возвратом 1. **Почему 431 провал.** Это ошибки парсинга, таймауты, смена вёрстки или блокировка? В счётчиках `failed` и `blocked` разведены, значит различие уже фиксируется — надо посмотреть тексты ошибок в логах. 2. **Не тот же ли это класс, что #2625** — молчаливый блок, засчитываемый как обычный сбой. У Домклика детект бана есть (`domclick_exceptions.py`), в отличие от Циана и Яндекса, но 60 blocked против 431 failed наводит на мысль, что распознаётся не всё. 3. **Нужна ли джоба вообще.** Домклик даёт 6501 активное объявление, и они собираются городской развёрткой. Что именно добавляет детальная догрузка и насколько это влияет на оценку — если немного, возвращать не обязательно. ## Как вернуть ```sql UPDATE scrape_schedules SET enabled = true WHERE source = 'domclick_detail_backfill'; ``` Отдельной миграцией, после того как причина провалов устранена и проверена хотя бы одним успешным прогоном вручную. ## Прочее из того же ревью (мелочи в комментариях миграции 206) Две формулировки слегка преувеличены, стоит поправить при ближайшем касании файла: - `:89` — «rows_inserted=0 во ВСЕХ 30 прогонах» для `yandex_newbuilding_sweep`: на деле в первой трети окна было 11 ненулевых, а подряд нулевые — последние 17 дней. Решение о недельном такте от этого не меняется. - `:29` — «20/30 banned мгновенно»: один из этих двадцати (прогон 693) успел выдать 108 вставок и 2792 обновления до бана. Связано: #2633, #2613 (мёртвые прокси), #2625 (молчаливые блоки).
Collaborator

Диагностика проведена (read-only; сырые логи периода утеряны — контейнер пересоздан деплоем 04.08, поэтому анализ по scrape_runs.counters × код).

Вердикт: это класс #2625 — нераспознанный блок, не вёрстка и не таймауты

Корень: providers/domclick/detail.py _BLOCK_MARKERS проверяет 4 из 6 канонических QRATOR-маркеров — отсутствуют bot_mitigation, система защиты, 403 | домклик (полный список — в serp.py Layer A того же провайдера и в докстринге domclick_exceptions.py). QRATOR-страница с такими текстами пролетает мимо детекта → DomClickParseError("__SSR_STATE__ not found")failed, а не blocked.

Два следствия:

  1. Счётчик врёт: 431 «failed» — в значимой части тихие блоки (паттерн B: 7 прогонов по 18–100 попыток, 100% fail при blocked=0 — run 1075: 100/100, run 2813: 48/48; день-в-день непостоянство = разный текст challenge-страницы, не дрейф вёрстки).
  2. Хуже: не инкрементится consecutive_blocks → block-breaker (стоп на 3) не срабатывает → «тихо заблокированный» прогон прожигает весь батч по заблокированному ресурсу — ровно удары по репутации выделенного узла, от которых миграция 206 и защищалась. Live-подтверждение, что QRATOR блокирует и на здоровом прокси: 05.08 05:44 domclick_city_sweep поймал QRATOR block during rooms='st'.

Бонус-находка: тест блока в test_domclick_detail.py использует текст "Access denied by DataDome captcha" — DataDome это анти-бот Авито, не Домклика (скопированный шаблон).

Нужна ли джоба (п.3)

Да, но с оговоркой о масштабе: detail-поля реально используются эстиматором (repair_state — настоящий enum вместо текст-эвристики SERP, has_balcony — полноценный параметр модели, kitchen_area_m2 — comp-scoring #2012). Но ~94% корпуса (6296 листингов) уже разово обогащены bulk-механизмом 18.07 (70-секундное окно — не этот пайплайн); live-джоба нужна для инкремента новых: сейчас 208 активных pending.

План возврата

  1. Фикс маркеров: общий constant (6 маркеров) для serp+detail, чтобы списки не расходились снова + лог первых ~300 символов непроматченного HTML при ParseError (будущий дрейф не будет молчаливым) + тест с реальными QRATOR-текстами. → PR уже в работе.
  2. Ручной тестовый прогон 10–20 листингов: blocked должен расти вместо failed.
  3. Только затем enabled=true отдельной миграцией.
Диагностика проведена (read-only; сырые логи периода утеряны — контейнер пересоздан деплоем 04.08, поэтому анализ по `scrape_runs.counters` × код). ## Вердикт: это класс #2625 — нераспознанный блок, не вёрстка и не таймауты **Корень:** `providers/domclick/detail.py` `_BLOCK_MARKERS` проверяет **4 из 6** канонических QRATOR-маркеров — отсутствуют `bot_mitigation`, `система защиты`, `403 | домклик` (полный список — в `serp.py` Layer A того же провайдера и в докстринге `domclick_exceptions.py`). QRATOR-страница с такими текстами пролетает мимо детекта → `DomClickParseError("__SSR_STATE__ not found")` → `failed`, а не `blocked`. **Два следствия:** 1. Счётчик врёт: 431 «failed» — в значимой части тихие блоки (паттерн B: 7 прогонов по 18–100 попыток, 100% fail при blocked=0 — run 1075: 100/100, run 2813: 48/48; день-в-день непостоянство = разный текст challenge-страницы, не дрейф вёрстки). 2. Хуже: не инкрементится `consecutive_blocks` → block-breaker (стоп на 3) не срабатывает → «тихо заблокированный» прогон прожигает весь батч по заблокированному ресурсу — ровно удары по репутации выделенного узла, от которых миграция 206 и защищалась. Live-подтверждение, что QRATOR блокирует и на здоровом прокси: 05.08 05:44 `domclick_city_sweep` поймал `QRATOR block during rooms='st'`. Бонус-находка: тест блока в `test_domclick_detail.py` использует текст `"Access denied by DataDome captcha"` — DataDome это анти-бот Авито, не Домклика (скопированный шаблон). ## Нужна ли джоба (п.3) Да, но с оговоркой о масштабе: detail-поля реально используются эстиматором (`repair_state` — настоящий enum вместо текст-эвристики SERP, `has_balcony` — полноценный параметр модели, `kitchen_area_m2` — comp-scoring #2012). Но ~94% корпуса (6296 листингов) уже разово обогащены bulk-механизмом 18.07 (70-секундное окно — не этот пайплайн); live-джоба нужна для инкремента новых: сейчас 208 активных pending. ## План возврата 1. Фикс маркеров: общий constant (6 маркеров) для serp+detail, чтобы списки не расходились снова + лог первых ~300 символов непроматченного HTML при ParseError (будущий дрейф не будет молчаливым) + тест с реальными QRATOR-текстами. → PR уже в работе. 2. Ручной тестовый прогон 10–20 листингов: blocked должен расти вместо failed. 3. Только затем `enabled=true` отдельной миграцией.
Collaborator

Полный цикл возврата завершён:

  1. Диагностика (коммент выше) — корень: detail-слой знал 4 из 6 QRATOR-маркеров, блоки уходили в failed, breaker не срабатывал.
  2. Фикс — PR #2645 (merged + прод-verified): единый DOMCLICK_BLOCK_MARKERS (7) для serp+detail + warning-лог непроматченного HTML.
  3. Живой ручной прогон 05.08 (шаг 2): карточка 2078185446 → полное обогащение (repair_state, year_built, ЕГРН-площадь) — первый успешный live-фетч detail-фазы; карточка 2078446537 → challenge → DomClickBlockedError («markers checked: (7)») — детект работает, breaker снова функционален.
  4. Возврат — PR #2647 (merged): миграция 208 enabled=true.

Страховка: следующие прогоны либо дадут enriched>0, либо честный banned (не done с нулём) — а zero-result-алерт из #2642 поднимет шум, если что-то снова тихо сломается. Мелочи из «прочего» (формулировки в 206) не правил — файл уже применён, исторические комменты не трогаю. Закрываю.

Полный цикл возврата завершён: 1. **Диагностика** (коммент выше) — корень: detail-слой знал 4 из 6 QRATOR-маркеров, блоки уходили в failed, breaker не срабатывал. 2. **Фикс** — PR #2645 (merged + прод-verified): единый `DOMCLICK_BLOCK_MARKERS` (7) для serp+detail + warning-лог непроматченного HTML. 3. **Живой ручной прогон 05.08** (шаг 2): карточка `2078185446` → полное обогащение (repair_state, year_built, ЕГРН-площадь) — первый успешный live-фетч detail-фазы; карточка `2078446537` → challenge → `DomClickBlockedError` («markers checked: (7)») — детект работает, breaker снова функционален. 4. **Возврат** — PR #2647 (merged): миграция 208 `enabled=true`. Страховка: следующие прогоны либо дадут `enriched>0`, либо честный `banned` (не `done` с нулём) — а zero-result-алерт из #2642 поднимет шум, если что-то снова тихо сломается. Мелочи из «прочего» (формулировки в 206) не правил — файл уже применён, исторические комменты не трогаю. Закрываю.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2636
No description provided.