fix(tradein/domclick): перезапуск браузера на карточку уничтожает пропуск QRATOR — лечим симптом, который сами и создаём #3212

Closed
opened 2026-08-29 10:59:12 +00:00 by lekss361 · 1 comment
Owner

Что происходит

ДомКлик закрыт антиботом QRATOR с proof-of-work. Порядок такой:

  1. первый запрос отдаёт 401 и крошечную заглушку с задачей PoW;
  2. браузер её решает и дёргает GET /__qrator/validate?pow=…&nonce=…;
  3. в ответ 200 и пропуск в кукахqrator_jsid2 + qrator_jsr;
  4. дальше карточки открываются свободно, validate больше не вызывается.

Пропуск живёт в cookie jar, то есть в browser context'е. Прод берёт каждую карточку через browser.new_page() — а это НОВЫЙ контекст с новой банкой кук. Пропуск выбрасывается, на следующей карточке QRATOR получает повторную валидацию с того же IP и отвечает 403 + страница bot-mitigation (~26 625 байт).

Замер (прод, прод-прокси, camoufox, по 6 карточек на условие)

условие успех вызовы /__qrator/validate
A один контекст, одна вкладка 6/6 [] на каждой карточке
B один контекст, новая вкладка на карточку 6/6 [] на каждой карточке
C новый контекст на карточку (= прод) 1/6 [304, 403] на каждой

Вкладки роли не играют. Играет роль общий контекст.

Почему #3205 (recycle_pages=1 для domclick) — неверное лечение

Тот PR перезапускает процесс camoufox после каждой страницы. Перезапуск гарантированно уничтожает контекст — то есть борется с симптомом, который сам же и создаёт. Побочно: ~23.6 с на карточку и всё равно не 100% (18/20 в замере).

Замер 6/6, который приняли за доказательство переиспользования контекста, оказался испорчен: в логах сайдкара после каждой страницы стоит recycle threshold (1) достигнут, перезапуск браузера. То есть проверяли не то, что думали.

Отдельно неверна формулировка в #3204/#3205 «страница отказа, а не челлендж» — челлендж есть, он PoW-шный, просто мы читаем HTML до того, как он решён.

Почему не сработал #3193 (reuse_context=True)

domclick_detail_backfill вызывает bf.request_context_reset() на каждый блок. Сброс контекста = потеря пропуска = следующая карточка тоже блок = следующий сброс. Одна случайная осечка превращается в необратимый каскад, что ровно и даёт наблюдавшийся «1 успех из 10».

Что делать

  1. Снять domclick: 1 из _RECYCLE_PAGES_DEFAULT_BY_PROVIDER (per-provider ручка и domclick как отдельный провайдер из #3205 — полезны, остаются).
  2. Не сбрасывать контекст на каждый блок: пробовать свежий контекст один раз на серию, а не после каждой осечки.
  3. Починить распознавание челленджа в сайдкаре: _CHALLENGE_MARKERS ищет startpow, а заглушка QRATOR несёт __qrator; при BROWSER_WAIT_MS=4500 HTML читается раньше, чем PoW решён.
## Что происходит ДомКлик закрыт антиботом QRATOR с proof-of-work. Порядок такой: 1. первый запрос отдаёт `401` и крошечную заглушку с задачей PoW; 2. браузер её решает и дёргает `GET /__qrator/validate?pow=…&nonce=…`; 3. в ответ `200` и **пропуск в куках** — `qrator_jsid2` + `qrator_jsr`; 4. дальше карточки открываются свободно, `validate` больше не вызывается. Пропуск живёт в cookie jar, то есть **в browser context'е**. Прод берёт каждую карточку через `browser.new_page()` — а это НОВЫЙ контекст с новой банкой кук. Пропуск выбрасывается, на следующей карточке QRATOR получает повторную валидацию с того же IP и отвечает `403` + страница bot-mitigation (~26 625 байт). ## Замер (прод, прод-прокси, camoufox, по 6 карточек на условие) | условие | успех | вызовы `/__qrator/validate` | |---|---|---| | A один контекст, одна вкладка | **6/6** | `[]` на каждой карточке | | B один контекст, новая вкладка на карточку | **6/6** | `[]` на каждой карточке | | C новый контекст на карточку (= прод) | **1/6** | `[304, 403]` на каждой | Вкладки роли не играют. Играет роль **общий контекст**. ## Почему #3205 (recycle_pages=1 для domclick) — неверное лечение Тот PR перезапускает процесс camoufox после каждой страницы. Перезапуск гарантированно уничтожает контекст — то есть борется с симптомом, который сам же и создаёт. Побочно: ~23.6 с на карточку и всё равно не 100% (18/20 в замере). Замер 6/6, который приняли за доказательство переиспользования контекста, оказался испорчен: в логах сайдкара после каждой страницы стоит `recycle threshold (1) достигнут, перезапуск браузера`. То есть проверяли не то, что думали. Отдельно неверна формулировка в #3204/#3205 «страница отказа, а не челлендж» — челлендж есть, он PoW-шный, просто мы читаем HTML до того, как он решён. ## Почему не сработал #3193 (`reuse_context=True`) `domclick_detail_backfill` вызывает `bf.request_context_reset()` **на каждый блок**. Сброс контекста = потеря пропуска = следующая карточка тоже блок = следующий сброс. Одна случайная осечка превращается в необратимый каскад, что ровно и даёт наблюдавшийся «1 успех из 10». ## Что делать 1. Снять `domclick: 1` из `_RECYCLE_PAGES_DEFAULT_BY_PROVIDER` (per-provider ручка и `domclick` как отдельный провайдер из #3205 — полезны, остаются). 2. Не сбрасывать контекст на каждый блок: пробовать свежий контекст один раз на серию, а не после каждой осечки. 3. Починить распознавание челленджа в сайдкаре: `_CHALLENGE_MARKERS` ищет `startpow`, а заглушка QRATOR несёт `__qrator`; при `BROWSER_WAIT_MS=4500` HTML читается раньше, чем PoW решён.
Author
Owner

Проверено в коде на forgejo/main — сделано, закрываю.

PR #3217 (merged 2026-08-29) — сброс context'а разрешён ровно один раз за прогон (tasks/domclick_detail_backfill.py:308). Остаток по _CHALLENGE_MARKERS неактуален: символа в коде больше нет.

Проверено в коде на forgejo/main — сделано, закрываю. PR #3217 (merged 2026-08-29) — сброс context'а разрешён ровно один раз за прогон (tasks/domclick_detail_backfill.py:308). Остаток по `_CHALLENGE_MARKERS` неактуален: символа в коде больше нет.
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#3212
No description provided.