fix(tradein/cian): обогащение ЖК падало не на разметке, а на сожжённом узле (#2767) #2798

Merged
bot-backend merged 1 commit from fix/2767-cian-newbuilding-markup into main 2026-08-09 17:38:40 +00:00
Collaborator

Что оказалось на странице

Живая проба 2026-08-09 тем же трактом, что у задачи (изнутри tradein-scraper → сайдкар → camoufox → узел прокси), одна и та же страница zhk-pihtovyy-ekb-i.cian.ru, один заход:

узел размер что пришло
#1 asocks-residential-1 374 168 Б cian_waf_block, initialState нет
#9 asocks-mobile-1 542 021 Б initialState ЕСТЬ
#10 asocks-mobile-2 557 235 Б initialState ЕСТЬ
#11 asocks-mobile-3 557 163 Б initialState ЕСТЬ

Страница в 374 КБ — не карточка ЖК и не SPA-оболочка. Это страница блокировки Циана: <title>Ошибка - Циан</title>, текст «Обнаружен подозрительный трафик», код страницы cian_waf_block, и её собственная аналитика помечает себя pageType:"VPNBlock", extra:{antibot:true}. Одинаковый до байта размер у разных ЖК объясняется тем, что различаются только IP и UUID запроса — обе строки фиксированной длины. 374 КБ набегают инлайн-аналитикой, поэтому по размеру блок неотличим от целой карточки.

Где состояние

Там же, где было. MFE newbuilding-card-desktop-frontend, ключ initialStateтекущий код разбирает его на трёх узлах из четырёх без единой правки регулярки. Гипотеза «Циан сменил разметку» опровергнута.

Что было сломано на самом деле

fetch_newbuilding — единственный cian-путь, который строил BrowserFetcher вручную, без proxy_provider (cian/serp.py всегда шёл через build_browser_fetcher). Пропуск задокументирован в самой фабрике как #2160 P4 wiring gap. Следствие: обогащение всегда выходило через один env-узел сайдкара — SCRAPER_PROXY_URL, он же узел пула #1, чей exit-IP Циан забанил. Ротация невозможна, report_ban без lease — no-op, 25 попыток за ночь уходили в тот же адрес. scrape_proxy_source_bans на проде содержит одну строку, и та про avito: cian-блоки не репортились никогда.

Диагностика #2768 при этом отвечала antibot_markers=none. Список маркеров не знал подписи cian_waf_block, а страница блока не содержит ни «captcha», ни «вы не робот», ни «доступ ограничен». Молчание списка прочиталось как его вердикт «защиты нет» — и увело разбор в гипотезу про разметку на восемь суток.

Правки

  • fetch_newbuilding принимает proxy_provider и строится через build_browser_fetcher — пул, как у всех остальных cian-путей. config=None остаётся законным (admin debug-роут), фабрика применяется только когда config есть.
  • Блок репортится в пул как бан узла до выхода из async with, пока lease жив: после выхода узел уже отпущен и вызов был бы no-op.
  • cian_waf_block добавлен в _ANTIBOT_MARKERS, с датой живой проверки. В docstring записано, что размер сам по себе гипотезы больше не разделяет.
  • proxy_provider прокинут во все три вызывающих: обогащение, cian_history_backfill, admin-роут.
  • Из лога убрано (captcha / parse miss?) — догадка автора кода, читавшаяся дальше как факт (пункт из тела issue).

Тест

tests/test_2767_cian_waf_block.py на фикстуре cian_waf_block_zhk_page.html — настоящий ответ прода (обрезаны инлайн-стили, текст блока и код страницы сохранены).

На коде до правки, на той же фикстуре:

OLD CODE ->  html_len=3740 antibot_markers=none
OLD CODE has _blocked_by: False
OLD CODE fetch_newbuilding params: ['zhk_url', 'config', 'session']

Отдельный тест фиксирует, что страница блока не содержит НИ ОДНОГО из прежних маркеров — иначе через полгода непонятно, зачем добавлен новый.

Test plan

  • pytest -k "newbuilding or cian or proxy or browser" — 480 passed, 1 skipped
  • ruff check + format
  • прод: ближайший прогон newbuilding_enrichenriched > 0 И свежие строки в houses_price_dynamics (последняя запись там — 2026-07-26)

Чего эта правка НЕ делает

Не чинит сам факт бана узла #1 — он остаётся сожжённым для Циана, правка лишь перестаёт в него упираться и учит пул это запоминать. Если Циан забанит и мобильные узлы, обогащение снова встанет — но тогда журнал скажет antibot_markers=cian_waf_block, а не none.

Refs #2767

## Что оказалось на странице Живая проба 2026-08-09 тем же трактом, что у задачи (изнутри `tradein-scraper` → сайдкар → camoufox → узел прокси), одна и та же страница `zhk-pihtovyy-ekb-i.cian.ru`, один заход: | узел | размер | что пришло | |---|---|---| | #1 `asocks-residential-1` | 374 168 Б | `cian_waf_block`, initialState **нет** | | #9 `asocks-mobile-1` | 542 021 Б | initialState **ЕСТЬ** | | #10 `asocks-mobile-2` | 557 235 Б | initialState **ЕСТЬ** | | #11 `asocks-mobile-3` | 557 163 Б | initialState **ЕСТЬ** | Страница в 374 КБ — не карточка ЖК и не SPA-оболочка. Это страница блокировки Циана: `<title>Ошибка - Циан</title>`, текст «Обнаружен подозрительный трафик», код страницы `cian_waf_block`, и её собственная аналитика помечает себя `pageType:"VPNBlock", extra:{antibot:true}`. Одинаковый до байта размер у разных ЖК объясняется тем, что различаются только IP и UUID запроса — обе строки фиксированной длины. 374 КБ набегают инлайн-аналитикой, поэтому по размеру блок неотличим от целой карточки. ## Где состояние Там же, где было. MFE `newbuilding-card-desktop-frontend`, ключ `initialState` — **текущий** код разбирает его на трёх узлах из четырёх без единой правки регулярки. Гипотеза «Циан сменил разметку» опровергнута. ## Что было сломано на самом деле `fetch_newbuilding` — единственный cian-путь, который строил `BrowserFetcher` вручную, без `proxy_provider` (`cian/serp.py` всегда шёл через `build_browser_fetcher`). Пропуск задокументирован в самой фабрике как #2160 P4 wiring gap. Следствие: обогащение всегда выходило через один env-узел сайдкара — `SCRAPER_PROXY_URL`, он же узел пула #1, чей exit-IP Циан забанил. Ротация невозможна, `report_ban` без lease — no-op, 25 попыток за ночь уходили в тот же адрес. `scrape_proxy_source_bans` на проде содержит одну строку, и та про avito: cian-блоки не репортились никогда. Диагностика #2768 при этом отвечала `antibot_markers=none`. Список маркеров не знал подписи `cian_waf_block`, а страница блока не содержит ни «captcha», ни «вы не робот», ни «доступ ограничен». **Молчание списка прочиталось как его вердикт «защиты нет»** — и увело разбор в гипотезу про разметку на восемь суток. ## Правки - `fetch_newbuilding` принимает `proxy_provider` и строится через `build_browser_fetcher` — пул, как у всех остальных cian-путей. `config=None` остаётся законным (admin debug-роут), фабрика применяется только когда config есть. - Блок репортится в пул как бан узла **до** выхода из `async with`, пока lease жив: после выхода узел уже отпущен и вызов был бы no-op. - `cian_waf_block` добавлен в `_ANTIBOT_MARKERS`, с датой живой проверки. В docstring записано, что размер сам по себе гипотезы больше не разделяет. - `proxy_provider` прокинут во все три вызывающих: обогащение, `cian_history_backfill`, admin-роут. - Из лога убрано `(captcha / parse miss?)` — догадка автора кода, читавшаяся дальше как факт (пункт из тела issue). ## Тест `tests/test_2767_cian_waf_block.py` на фикстуре `cian_waf_block_zhk_page.html` — настоящий ответ прода (обрезаны инлайн-стили, текст блока и код страницы сохранены). На коде до правки, на той же фикстуре: ``` OLD CODE -> html_len=3740 antibot_markers=none OLD CODE has _blocked_by: False OLD CODE fetch_newbuilding params: ['zhk_url', 'config', 'session'] ``` Отдельный тест фиксирует, что страница блока не содержит НИ ОДНОГО из прежних маркеров — иначе через полгода непонятно, зачем добавлен новый. ## Test plan - [x] `pytest -k "newbuilding or cian or proxy or browser"` — 480 passed, 1 skipped - [x] ruff check + format - [ ] прод: ближайший прогон `newbuilding_enrich` → `enriched > 0` И свежие строки в `houses_price_dynamics` (последняя запись там — 2026-07-26) ## Чего эта правка НЕ делает Не чинит сам факт бана узла #1 — он остаётся сожжённым для Циана, правка лишь перестаёт в него упираться и учит пул это запоминать. Если Циан забанит и мобильные узлы, обогащение снова встанет — но тогда журнал скажет `antibot_markers=cian_waf_block`, а не `none`. Refs #2767
bot-backend added 1 commit 2026-08-09 17:15:10 +00:00
fix(tradein/cian): обогащение ЖК падало не на разметке, а на сожжённом узле (#2767)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m54s
70f2daf241
Живая проба 2026-08-09 тем же трактом (сайдкар → camoufox → узел пула), одна и та
же страница zhk-pihtovyy-ekb-i.cian.ru:

    узел #1  asocks-residential-1 → 374 168 Б, cian_waf_block, initialState нет
    узел #9  asocks-mobile-1      → 542 021 Б,                 initialState ЕСТЬ
    узел #10 asocks-mobile-2      → 557 235 Б,                 initialState ЕСТЬ
    узел #11 asocks-mobile-3      → 557 163 Б,                 initialState ЕСТЬ

Разметка не менялась: MFE 'newbuilding-card-desktop-frontend'/'initialState'
разбирается ТЕКУЩИМ кодом на трёх узлах из четырёх. Страница в 374 КБ — не
карточка и не SPA-оболочка, а страница блокировки Циана: «Обнаружен
подозрительный трафик», код страницы cian_waf_block, собственная аналитика
помечает её pageType:"VPNBlock".

Почему это восемь суток читалось как смена разметки: fetch_newbuilding была
единственным cian-путём, который строил BrowserFetcher вручную, без
proxy_provider (serp.py всегда шёл через build_browser_fetcher). Значит сбор
всегда выходил через ОДИН env-узел сайдкара — SCRAPER_PROXY_URL, он же узел
пула #1, чей exit-IP Циан забанил. Ротация была невозможна, report_ban без
lease — no-op, 25 попыток за ночь уходили в тот же адрес.

Диагностика #2768 при этом отвечала «antibot_markers=none»: список маркеров не
знал подписи cian_waf_block, а страница блока не содержит ни «captcha», ни «вы
не робот». Молчание списка прочиталось как его вердикт «защиты нет» — и увело
разбор в гипотезу про разметку.

Правки:
- fetch_newbuilding принимает proxy_provider и строится через
  build_browser_fetcher (пул, как у всех остальных cian-путей);
- страница блока репортится в пул как бан узла ДО выхода из контекста, пока
  lease жив, — дальше acquire('cian') этот узел не выдаёт;
- cian_waf_block добавлен в _ANTIBOT_MARKERS; размер сам по себе гипотезы
  больше не разделяет (блок весит 374 КБ) — это записано в docstring;
- proxy_provider прокинут во все три вызывающих: обогащение, cian_history,
  admin debug-роут;
- из лога убрано «(captcha / parse miss?)» — догадка автора кода, читавшаяся
  дальше как факт.

Тест на НАСТОЯЩЕМ сохранённом ответе прода (фикстура cian_waf_block_zhk_page.html,
обрезаны инлайн-стили). На коде до правки: _describe_parse_miss даёт
«antibot_markers=none», _blocked_by нет, аргумента proxy_provider нет.

Refs #2767
bot-backend merged commit f3bcb1a25f into main 2026-08-09 17:38:40 +00:00
bot-backend deleted branch fix/2767-cian-newbuilding-markup 2026-08-09 17:38:41 +00:00
Sign in to join this conversation.
No reviewers
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#2798
No description provided.