fix(tradein/cian): банить узел только когда состояния НЕТ, а не по слову «captcha» (#2767) #2801

Merged
bot-backend merged 1 commit from fix/2767-ban-only-on-parse-miss into main 2026-08-09 18:04:02 +00:00
Collaborator

Живая регрессия предыдущего PR (#2798), поймана на проде через 17 секунд после деплоя

17:47:44 WARNING BrowserFetcher: lease id=9 (cian) BANNED — reporting to pool: cian newbuilding: captcha
17:47:44 INFO    Cian newbuilding https://zhk-tihiy-centr-ekb-i.cian.ru parsed: id=108855 reliability=1

Одна и та же страница в одну и ту же секунду: разобрана успешно И объявлена блоком. За первую минуту прогона так забанились два ЗДОРОВЫХ узла — 9 и 10, оба из тех трёх, на которых страница как раз и достаётся.

Причина простая: обычная карточка ЖК грузит скрипт SmartCaptcha, подстрока «captcha» на ней есть всегда.

Что я сделал не так

Признак сменил смысл при переносе. _ANTIBOT_MARKERS создавался объяснять уже случившийся отказ разбора: _describe_parse_miss зовётся ровно из одной ветки — «состояния нет» — и там подстрока действительно значит блок. Применённый как самостоятельный детектор на каждом ответе, тот же список означает уже другое: «страница упоминает капчу».

Это ровно тот класс, который в этом же issue разбирали про диагностику со знаком вопроса, только с другой стороны: там слабый признак прочитали как факт, здесь — как решение.

Правка

Разбор перенесён внутрь async with (бан обязан репортиться, пока lease жив), и бан репортится только когда nb_state is None И найдена подпись. Условие «состояния нет» здесь несущее, а не уточняющее.

Тест

Здоровая карточка в текущем формате Циана (.concat([...]) с initialState), содержащая слово-ловушку. На смерженном коде:

E   AssertionError: Expected 'report_ban' to not have been called. Called 1 times.
E   Calls: [call('cian newbuilding: captcha')].

Тест утверждает и свою предпосылку — что страница действительно разбирается и слово на ней есть, — иначе он зеленел бы по неверной причине.

Test plan

  • pytest tests/test_2767_cian_waf_block.py tests/test_2767_newbuilding_parse_miss.py tests/test_scraper_kit_newbuilding_endpoint.py — 20 passed
  • ruff
  • прод: следующий прогон newbuilding_enrich без строк BANNED на разобранных страницах

Побочный эффект, который надо снять руками

В scrape_proxy_source_bans от ошибочной версии остались строки proxy_id 9/10, source=cian, banned_until 2026-08-09 23:47/23:48. Узлы здоровы; бан истекает сам через ~6 ч, но снять раньше — просто DELETE ... WHERE source='cian'.

Refs #2767

## Живая регрессия предыдущего PR (#2798), поймана на проде через 17 секунд после деплоя ``` 17:47:44 WARNING BrowserFetcher: lease id=9 (cian) BANNED — reporting to pool: cian newbuilding: captcha 17:47:44 INFO Cian newbuilding https://zhk-tihiy-centr-ekb-i.cian.ru parsed: id=108855 reliability=1 ``` Одна и та же страница в одну и ту же секунду: **разобрана успешно И объявлена блоком**. За первую минуту прогона так забанились два ЗДОРОВЫХ узла — 9 и 10, оба из тех трёх, на которых страница как раз и достаётся. Причина простая: обычная карточка ЖК грузит скрипт SmartCaptcha, подстрока «captcha» на ней есть **всегда**. ## Что я сделал не так Признак сменил смысл при переносе. `_ANTIBOT_MARKERS` создавался объяснять **уже случившийся** отказ разбора: `_describe_parse_miss` зовётся ровно из одной ветки — «состояния нет» — и там подстрока действительно значит блок. Применённый как самостоятельный детектор на каждом ответе, тот же список означает уже другое: «страница упоминает капчу». Это ровно тот класс, который в этом же issue разбирали про диагностику со знаком вопроса, только с другой стороны: там слабый признак прочитали как факт, здесь — как решение. ## Правка Разбор перенесён внутрь `async with` (бан обязан репортиться, пока lease жив), и бан репортится только когда `nb_state is None` **И** найдена подпись. Условие «состояния нет» здесь несущее, а не уточняющее. ## Тест Здоровая карточка в текущем формате Циана (`.concat([...])` с `initialState`), содержащая слово-ловушку. На смерженном коде: ``` E AssertionError: Expected 'report_ban' to not have been called. Called 1 times. E Calls: [call('cian newbuilding: captcha')]. ``` Тест утверждает и свою предпосылку — что страница действительно разбирается и слово на ней есть, — иначе он зеленел бы по неверной причине. ## Test plan - [x] `pytest tests/test_2767_cian_waf_block.py tests/test_2767_newbuilding_parse_miss.py tests/test_scraper_kit_newbuilding_endpoint.py` — 20 passed - [x] ruff - [ ] прод: следующий прогон `newbuilding_enrich` без строк BANNED на разобранных страницах ## Побочный эффект, который надо снять руками В `scrape_proxy_source_bans` от ошибочной версии остались строки `proxy_id 9/10, source=cian, banned_until 2026-08-09 23:47/23:48`. Узлы здоровы; бан истекает сам через ~6 ч, но снять раньше — просто `DELETE ... WHERE source='cian'`. Refs #2767
bot-backend added 1 commit 2026-08-09 17:51:08 +00:00
fix(tradein/cian): банить узел только когда состояния НЕТ, а не по слову «captcha» (#2767)
All checks were successful
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
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 4m2s
876bf378e9
Живая регрессия предыдущего PR, поймана на проде через 17 секунд после деплоя:

    17:47:44 BrowserFetcher: lease id=9 (cian) BANNED — cian newbuilding: captcha
    17:47:44 Cian newbuilding zhk-tihiy-centr-ekb-i.cian.ru parsed: id=108855

Одна и та же страница в одну и ту же секунду: разобрана успешно И объявлена
блоком. За минуту так забанились два ЗДОРОВЫХ узла (9 и 10). Причина: обычная
карточка ЖК грузит скрипт SmartCaptcha, подстрока «captcha» на ней есть всегда.

Ошибка была в том, что признак сменил смысл при переносе. `_ANTIBOT_MARKERS`
создавался объяснять УЖЕ СЛУЧИВШИЙСЯ отказ разбора — `_describe_parse_miss`
зовётся только из ветки «состояния нет», и там подстрока действительно значит
блок. Применённый как самостоятельный детектор на каждом ответе, тот же список
означает уже другое: «страница упоминает капчу».

Разбор перенесён внутрь `async with`, бан репортится только при
`nb_state is None` И найденной подписи. Условие «нет состояния» несущее, а не
уточняющее.

Тест на здоровой карточке в текущем формате Циана, содержащей слово-ловушку:
красный на смерженном коде (report_ban called 1 times), зелёный здесь.

Refs #2767
bot-backend merged commit f45ce3be2d into main 2026-08-09 18:04:02 +00:00
bot-backend deleted branch fix/2767-ban-only-on-parse-miss 2026-08-09 18:04:03 +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#2801
No description provided.