DomClick scraper мёртв: VPS-IP заблокирован QRATOR + редизайн сайта (нужен прокси + rewrite на новый API) #1846

Closed
opened 2026-06-20 17:59:15 +00:00 by lekss361 · 3 comments
Owner

Симптом

domclick_city_sweep тихо «done» с 0 листингов (pages_fetched=25, lots_fetched=0, errors=0). В UI «ДомКлик Прайс: нет данных». Источник давно не даёт ничего.

Root cause (диагностика live 2026-06-20) — ДВЕ проблемы

1. VPS-IP заблокирован QRATOR'ом DomClick. Любой URL domclick.ru возвращает HTTP 200 + Gatsby/QRATOR anti-bot страницу ошибки (26625 байт, title «403 | Домклик»): «Система защиты могла принять ваши действия за автоматические… IP-адрес: 92.36.20.211» (= IP VPS gendesign). Блок на уровне IP (QRATOR, поверх camoufox). Не DataDome, не DOM-дрейф сам по себе — IP забанен.

  • curl_cffi с обычным UA → QRATOR 401; через camoufox → 200 + bot_mitigation страница.
  • Googlebot/YandexBot UA → всё равно 401 (IP-блок сильнее UA).

2. Сайт редизайнут (даже с чистым IP старый URL мёртв). Statics → dmclk.ru, SPA = React+Vite (не Gatsby). Старый /search?...city_id=4&p=N устарел. Новый источник листингов:

  • GET api.domclick.ru/api/offers/v1?deal_type=sale&offer_type=flat&aids[]=<EKB_AID>&limit=20&offset=0&sort=qi&sort_dir=desc
  • Геофильтр теперь aids (массив внутренних DomClick geo-ID), НЕ Sberbank city_id=4. ЕКБ aids берётся через GET api.domclick.ru/api/suggester/v1?text=Екатеринбург.
  • Прямые вызовы api.domclick.ru → Kong 404 «no Route matched» (роут живёт только в SPA-контексте с cookies/auth + чистый IP).

Что нужно (fix plan)

  1. Резидентный/мобильный прокси для source="domklik" в BrowserFetcher pool (аналогично avito mobile proxy, runbook avito_mobile_proxy.md) — VPS IP забанен, нужен чистый РФ-IP. DomClick пропускает браузерные запросы с нормального IP.
  2. Rewrite domclick.py под текущий сайт: через браузер (с чистым IP) зайти на domclick.ru/search?deal_type=sale&offer_type=flat, перехватить XHR к /api/offers/v1, получить ЕКБ aids (через suggester), переписать _build_url (новый endpoint + aids) и _parse_html (JSON вместо HTML-карточек).
  3. Файлы: app/services/scrapers/domclick.py (_build_url, _parse_html), proxy-конфиг (server.py/BrowserFetcher pool — добавить domclick source с прокси).

Приоритет

Низкий / supplementary. avito (чисто, full_load done) + cian + yandex покрывают вторичку ЕКБ + кросс-валидацию. DomClick — доп. источник. Браться, когда дойдут руки / если нужна DomClick-кросс-валидация. Требует прокси (расход) + reverse-engineering API.

Источник: аудит скрапперов 2026-06-20 (diagnostic, без рабочего фикса — старый /search не воскрешается без прокси+rewrite).

## Симптом `domclick_city_sweep` тихо «done» с 0 листингов (pages_fetched=25, lots_fetched=0, errors=0). В UI «ДомКлик Прайс: нет данных». Источник давно не даёт ничего. ## Root cause (диагностика live 2026-06-20) — ДВЕ проблемы **1. VPS-IP заблокирован QRATOR'ом DomClick.** Любой URL `domclick.ru` возвращает HTTP 200 + **Gatsby/QRATOR anti-bot страницу ошибки** (26625 байт, title «403 | Домклик»): _«Система защиты могла принять ваши действия за автоматические… IP-адрес: 92.36.20.211»_ (= IP VPS `gendesign`). Блок на уровне IP (QRATOR, поверх camoufox). Не DataDome, не DOM-дрейф сам по себе — **IP забанен**. - curl_cffi с обычным UA → QRATOR 401; через camoufox → 200 + bot_mitigation страница. - Googlebot/YandexBot UA → всё равно 401 (IP-блок сильнее UA). **2. Сайт редизайнут (даже с чистым IP старый URL мёртв).** Statics → `dmclk.ru`, SPA = React+Vite (не Gatsby). Старый `/search?...city_id=4&p=N` устарел. Новый источник листингов: - `GET api.domclick.ru/api/offers/v1?deal_type=sale&offer_type=flat&aids[]=<EKB_AID>&limit=20&offset=0&sort=qi&sort_dir=desc` - Геофильтр теперь **`aids` (массив внутренних DomClick geo-ID)**, НЕ Sberbank `city_id=4`. ЕКБ `aids` берётся через `GET api.domclick.ru/api/suggester/v1?text=Екатеринбург`. - Прямые вызовы api.domclick.ru → Kong 404 «no Route matched» (роут живёт только в SPA-контексте с cookies/auth + чистый IP). ## Что нужно (fix plan) 1. **Резидентный/мобильный прокси для `source="domklik"`** в BrowserFetcher pool (аналогично avito mobile proxy, runbook `avito_mobile_proxy.md`) — VPS IP забанен, нужен чистый РФ-IP. DomClick пропускает браузерные запросы с нормального IP. 2. **Rewrite `domclick.py`** под текущий сайт: через браузер (с чистым IP) зайти на `domclick.ru/search?deal_type=sale&offer_type=flat`, перехватить XHR к `/api/offers/v1`, получить ЕКБ `aids` (через suggester), переписать `_build_url` (новый endpoint + `aids`) и `_parse_html` (JSON вместо HTML-карточек). 3. Файлы: `app/services/scrapers/domclick.py` (`_build_url`, `_parse_html`), proxy-конфиг (`server.py`/BrowserFetcher pool — добавить domclick source с прокси). ## Приоритет **Низкий / supplementary.** avito (чисто, full_load done) + cian + yandex покрывают вторичку ЕКБ + кросс-валидацию. DomClick — доп. источник. Браться, когда дойдут руки / если нужна DomClick-кросс-валидация. Требует прокси (расход) + reverse-engineering API. Источник: аудит скрапперов 2026-06-20 (diagnostic, без рабочего фикса — старый /search не воскрешается без прокси+rewrite).
lekss361 added the
bug
priority/p3
scope/backend
scrapers
tradein
labels 2026-06-20 17:59:25 +00:00
Author
Owner

Layer A реанимирован и задеплоен — PR #1979 merged (2026-06-27).

Пере-оценка вердикта аудита («отказаться»): неверен. QRATOR — IP-репутация, не фингерпринт; обходится через уже подключённый shared mobile proxy (browser-pool роутит domclick.ru → generic provider). Новый аккаунт/правки browser-server НЕ нужны. Старый /search?city_id мёртв — переписано на живой bff-search-web.domclick.ru/api/offers/v1 + /count/v1 (в этом issue ошибочно искали api.domclick.ru → Kong 404).

Прод-smoke (live): scrape_domclick_city(pages=1)169 лотов, 100% с координатами, комнаты 0..7, годы 1930–2026. Координаты на каждом листинге — главный аргумент против «отказаться» (avito = 54% NULL lat).

  • Bucketing rooms {st,1,2,3,4,5+} × binary price-split (кап offset<2000); честный статус (0 лотов + ошибки → mark_failed, закрывает часть #1968).
  • Расписание domclick_city_sweep оставлено DORMANT (enabled=false) — включение после операторского решения.
  • Контракт API задокументирован в vault research/Domclick_Bff_Api_Contract_Jun27.md.

Остаётся (follow-up): Layer B — detail-карточка (/card/sale__flat__<id> SSR __SSR_STATE__): renovation/wallType/floorType/priceHistory/EGRN. Layer C — analytics XHR (offer-card.domclick.ru/api/v3/offers/price_prediction = AVM Домклика, sold_similar). Это самые ценные для estimator поля (renovation+wallType у avito 54% пустые) — стоит отдельным PR.

**Layer A реанимирован и задеплоен — PR #1979 merged (2026-06-27).** Пере-оценка вердикта аудита («отказаться»): неверен. QRATOR — IP-репутация, не фингерпринт; обходится через **уже подключённый** shared mobile proxy (browser-pool роутит `domclick.ru` → generic provider). Новый аккаунт/правки browser-server НЕ нужны. Старый `/search?city_id` мёртв — переписано на живой **`bff-search-web.domclick.ru/api/offers/v1`** + `/count/v1` (в этом issue ошибочно искали `api.domclick.ru` → Kong 404). **Прод-smoke (live):** `scrape_domclick_city(pages=1)` → **169 лотов, 100% с координатами**, комнаты 0..7, годы 1930–2026. Координаты на каждом листинге — главный аргумент против «отказаться» (avito = 54% NULL lat). - Bucketing rooms {st,1,2,3,4,5+} × binary price-split (кап offset<2000); честный статус (`0 лотов + ошибки → mark_failed`, закрывает часть #1968). - Расписание `domclick_city_sweep` оставлено **DORMANT** (`enabled=false`) — включение после операторского решения. - Контракт API задокументирован в vault `research/Domclick_Bff_Api_Contract_Jun27.md`. **Остаётся (follow-up):** Layer B — detail-карточка (`/card/sale__flat__<id>` SSR `__SSR_STATE__`): renovation/wallType/floorType/priceHistory/EGRN. Layer C — analytics XHR (`offer-card.domclick.ru/api/v3/offers/price_prediction` = AVM Домклика, `sold_similar`). Это самые ценные для estimator поля (renovation+wallType у avito 54% пустые) — стоит отдельным PR.
Author
Owner

Ре-скан 2026-07-04 (в рамках батча trade-in задач): статус изменился с даты постановки — Layer A уже реанимирован и задеплоен (PR #1979, см. комментарий выше), новый bff-search-web.domclick.ru/api/offers/v1 работает, прод-smoke 169 лотов/100% координат. Расписание domclick_city_sweep намеренно оставлено DORMANT (enabled=false).

Не кодирую здесь:

  1. Включение dormant-расписания — операторское решение (стоимость прокси-трафика / риск повторного QRATOR-бана), не код. Оставляю на решение user.
  2. Layer B (detail-карточка, domclick_detail.py) / Layer C (analytics AVM) — это ровно scope Group D (#2307) активной scraper_kit-миграции (#2277/#2304-2310, другое окно ведёт до конца автономно). domclick_detail.py явно упомянут в аудите #2277 как orphan-модуль без kit-эквивалента, который сначала портируется, потом легаси удаляется. Трогать не буду — коллизия с чужим mandate.

needs-human: только п.1 (включить schedule или нет).

Ре-скан 2026-07-04 (в рамках батча trade-in задач): статус изменился с даты постановки — Layer A уже реанимирован и задеплоен (PR #1979, см. комментарий выше), новый `bff-search-web.domclick.ru/api/offers/v1` работает, прод-smoke 169 лотов/100% координат. Расписание `domclick_city_sweep` намеренно оставлено DORMANT (`enabled=false`). Не кодирую здесь: 1. **Включение dormant-расписания** — операторское решение (стоимость прокси-трафика / риск повторного QRATOR-бана), не код. Оставляю на решение user. 2. **Layer B (detail-карточка, `domclick_detail.py`) / Layer C (analytics AVM)** — это ровно scope Group D (#2307) активной scraper_kit-миграции (#2277/#2304-2310, другое окно ведёт до конца автономно). `domclick_detail.py` явно упомянут в аудите #2277 как orphan-модуль без kit-эквивалента, который сначала портируется, потом легаси удаляется. Трогать не буду — коллизия с чужим mandate. needs-human: только п.1 (включить schedule или нет).
lekss361 added the
needs-human
label 2026-07-04 06:25:15 +00:00
Author
Owner

Stale — уже пофикшено. PR #1979 (merged 68438526, 2026-06-27) переписал SERP на BFF JSON API (bff-search-web.domclick.ru, aids-геофильтр через suggester) — ровно то, что описывает этот issue. Прод-smoke подтверждён: 169 лотов, 100% coords (см. research/Domclick_Bff_Api_Contract_Jun27.md в vault). PR не использовал closing-keyword синтаксис ((#1846, #1968) в скобках вместо closes #1846), отсюда issue висел открытым технически.

Follow-up (deep detail/Layer B, прокси-блокер) живёт отдельно в #2000. Closing.

Stale — уже пофикшено. PR #1979 (merged `68438526`, 2026-06-27) переписал SERP на BFF JSON API (`bff-search-web.domclick.ru`, `aids`-геофильтр через suggester) — ровно то, что описывает этот issue. Прод-smoke подтверждён: 169 лотов, 100% coords (см. `research/Domclick_Bff_Api_Contract_Jun27.md` в vault). PR не использовал closing-keyword синтаксис (`(#1846, #1968)` в скобках вместо `closes #1846`), отсюда issue висел открытым технически. Follow-up (deep detail/Layer B, прокси-блокер) живёт отдельно в #2000. Closing.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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#1846
No description provided.