tradein/scrapers: проверить Авито, Циан и Яндекс тем же способом, что вскрыл дефекты Домклика #3251

Open
opened 2026-08-29 20:03:44 +00:00 by lekss361 · 1 comment
Owner

Зачем

Разбор Домклика 29.08 нашёл два дефекта, которые не видны ни по логам, ни по тестам — только при сравнении машинного захода с человеческим в живом браузере:

  1. Referer не отправлялся никогдаpage.goto() его по умолчанию не шлёт, параметр referer не передавался. Площадка видела десяток появлений подряд прямо на URL карточки, без источника перехода.
  2. Зависшее рукопожатие не перезагружалось — весь механизм ожидания стоял на допущении «страница перезагрузит себя сама», которое выполняется не всегда; page.reload() в сайдкаре не вызывался нигде.

Оба починены в PR #3250, но чинились в сайдкаре, общем для всех площадок. Значит первая правка (Referer) сейчас включена только для Домклика — остальные провайдеры referer не передают, потому что их вызовы не обновляли. Вторая (перезагрузка) общая и уже действует на всех.

Что сделать

Повторить методику для Авито, Циана и Яндекса:

  1. Поднять headful-камуфокс локально через прод-прокси и пройти путь руками: поиск → выдача → карточка. Скрипт-регистратор готов, лежит в скрэтчпаде сессии (manual_domclick_session.py) — пишет сеть, консоль, куки, снимок сессии; тела запросов и заголовки намеренно НЕ пишет (через сессию идёт логин).
  2. Сравнить с тем, что делает наш скрапер по этой площадке: приходит ли с Referer, ждёт ли рукопожатие, перезагружает ли, сколько времени тратит на карточку.
  3. Для тех, кому Referer уместен, — передавать его так же, как в providers/domclick/detail.py (там referer=origin, origin = страница выдачи).

На что смотреть

  • У Авито тоже QRATOR с PoW (#3045) — механика ближе всего к Домклику, кандидат номер один.
  • Циан и Яндекс могут не использовать браузерный путь вовсе на части операций — сначала проверить, идёт ли карточка через сайдкар, и только потом мерить.
  • Полезная деталь из разбора Домклика: у него три состояния приходят под ОДНИМ кодом 401 и различаются только размером тела (279 Б загрузчик / ~7 КБ считается PoW / ровно 26 626 Б отказ / 500 КБ+ успех). У других площадок стоит проверить, нет ли такой же ловушки — статус как признак блока там может врать так же.

Связано

#3250 (обе правки), #3244 (якорная вкладка), #3246 (бан узла вместо сброса контекста), #3045 (PoW Авито).

## Зачем Разбор Домклика 29.08 нашёл два дефекта, которые не видны ни по логам, ни по тестам — только при сравнении машинного захода с человеческим в живом браузере: 1. **`Referer` не отправлялся никогда** — `page.goto()` его по умолчанию не шлёт, параметр `referer` не передавался. Площадка видела десяток появлений подряд прямо на URL карточки, без источника перехода. 2. **Зависшее рукопожатие не перезагружалось** — весь механизм ожидания стоял на допущении «страница перезагрузит себя сама», которое выполняется не всегда; `page.reload()` в сайдкаре не вызывался нигде. Оба починены в PR #3250, но чинились **в сайдкаре, общем для всех площадок**. Значит первая правка (Referer) сейчас включена только для Домклика — остальные провайдеры `referer` не передают, потому что их вызовы не обновляли. Вторая (перезагрузка) общая и уже действует на всех. ## Что сделать Повторить методику для Авито, Циана и Яндекса: 1. Поднять headful-камуфокс локально через прод-прокси и пройти путь руками: поиск → выдача → карточка. Скрипт-регистратор готов, лежит в скрэтчпаде сессии (`manual_domclick_session.py`) — пишет сеть, консоль, куки, снимок сессии; тела запросов и заголовки намеренно НЕ пишет (через сессию идёт логин). 2. Сравнить с тем, что делает наш скрапер по этой площадке: приходит ли с Referer, ждёт ли рукопожатие, перезагружает ли, сколько времени тратит на карточку. 3. Для тех, кому Referer уместен, — передавать его так же, как в `providers/domclick/detail.py` (там `referer=origin`, origin = страница выдачи). ## На что смотреть - У Авито тоже QRATOR с PoW (#3045) — механика ближе всего к Домклику, кандидат номер один. - Циан и Яндекс могут не использовать браузерный путь вовсе на части операций — сначала проверить, идёт ли карточка через сайдкар, и только потом мерить. - Полезная деталь из разбора Домклика: у него три состояния приходят под ОДНИМ кодом 401 и различаются только размером тела (279 Б загрузчик / ~7 КБ считается PoW / ровно 26 626 Б отказ / 500 КБ+ успех). У других площадок стоит проверить, нет ли такой же ловушки — статус как признак блока там может врать так же. ## Связано #3250 (обе правки), #3244 (якорная вкладка), #3246 (бан узла вместо сброса контекста), #3045 (PoW Авито).
Author
Owner

Авито: разбор по этой методике — нашлась третья правка, которой в тикете нет

Проверял Авито первым (кандидат номер один по тексту тикета). Кроме ожидаемого отсутствия Referer нашлась вещь тяжелее его.

Тёплый контекст: reuse_context не передаёт НИКТО, кроме Домклика

Единственный вызов во всём репозитории — backend/app/tasks/domclick_detail_backfill.py:346. Значит каждый /fetch Авито идёт через browser.new_page(), то есть новый изолированный context с пустой банкой кук на каждую карточку. Пропуск QRATOR, добытый proof-of-work'ом на предыдущей карточке, выбрасывается сразу же.

Видно прямо в логе прод-сайдкара: PoW-челлендж снят за ~1000мс печатается на КАЖДОЙ успешной карточке — челлендж решается заново каждый раз, а не один раз на прогон.

Эффект этой же правки у Домклика измерен и записан в domclick_detail_backfill.py:331-338: 26 последовательных фетчей сайдкара = 100% блок, те же карточки в тёплом контексте = 5/5 за ~2с.

Referer и origin — как и предполагалось

# providers/avito/detail.py:506
html = await browser_fetcher.fetch(full_url)                       # голый goto
# providers/domclick/detail.py:541
html = await browser_fetcher.fetch(card_url, origin=..., referer=..., cookies=...)

Важная механика сайдкара (browser/server.py:_fetch_once): при reuse_context=True origin поднимается ОДИН раз якорной вкладкой (_ensure_anchor_page), при reuse_context=False — полной лишней навигацией на каждую карточку. Поэтому origin/referer имеет смысл включать только вместе с тёплым контекстом, а не отдельно.

Заход через поиск Яндекса пока НЕ включаю

BROWSER_ANCHOR_VIA_SEARCH в прод-контейнере не задан → действует код-дефолт "domclick". Расширять список на Авито без отдельного замера не буду — ровно как написано в комментарии у константы.

База для сравнения (снята ДО правки)

avito_detail_backfill, доля блоков от попыток по суткам:

сутки прогонов попыток обогащено блоков доля блоков
25.08 8 228 111 107 46.9%
26.08 8 89 23 66 74.2%
27.08 10 56 1 54 96.4%
28.08 11 189 55 132 69.8%
29.08 8 658 306 348 52.9%
30.08 (3 прогона) 3 138 51 86 62.3%

Все прогоны без исключения заканчиваются banned по ratio-критерию, ban_kind=platform.

Сравнивать после выката буду по доле блоков от попыток и по обогащению за сутки, а НЕ по доле прогонов со статусом banned: критерий обрыва срабатывает всегда, и статус про площадку ничего не говорит (уже разбиралось при калибровке #3184).

Побочное наблюдение

В логах Авито заметная доля отказов — NS_ERROR_PROXY_BAD_GATEWAY и NS_ERROR_ABORT, то есть отказ прокси, а не площадки. В counters они, судя по всему, попадают в общий счётчик блоков и завышают «долю блоков площадки». Отдельно не чинил, но при чтении цифр это стоит держать в уме.

Дальше

PR на тёплый контекст + origin/referer для detail-бэкфилла Авито. Хранилище сессий и авторизованные куки (#3179 / #3180) — отдельно, эта правка их не заменяет и не блокирует.

## Авито: разбор по этой методике — нашлась третья правка, которой в тикете нет Проверял Авито первым (кандидат номер один по тексту тикета). Кроме ожидаемого отсутствия `Referer` нашлась вещь тяжелее его. ### Тёплый контекст: `reuse_context` не передаёт НИКТО, кроме Домклика Единственный вызов во всём репозитории — `backend/app/tasks/domclick_detail_backfill.py:346`. Значит каждый `/fetch` Авито идёт через `browser.new_page()`, то есть **новый изолированный context с пустой банкой кук на каждую карточку**. Пропуск QRATOR, добытый proof-of-work'ом на предыдущей карточке, выбрасывается сразу же. Видно прямо в логе прод-сайдкара: `PoW-челлендж снят за ~1000мс` печатается на КАЖДОЙ успешной карточке — челлендж решается заново каждый раз, а не один раз на прогон. Эффект этой же правки у Домклика измерен и записан в `domclick_detail_backfill.py:331-338`: 26 последовательных фетчей сайдкара = 100% блок, те же карточки в тёплом контексте = 5/5 за ~2с. ### Referer и origin — как и предполагалось ```python # providers/avito/detail.py:506 html = await browser_fetcher.fetch(full_url) # голый goto # providers/domclick/detail.py:541 html = await browser_fetcher.fetch(card_url, origin=..., referer=..., cookies=...) ``` Важная механика сайдкара (`browser/server.py:_fetch_once`): при `reuse_context=True` origin поднимается ОДИН раз якорной вкладкой (`_ensure_anchor_page`), при `reuse_context=False` — полной лишней навигацией на каждую карточку. Поэтому origin/referer имеет смысл включать только вместе с тёплым контекстом, а не отдельно. ### Заход через поиск Яндекса пока НЕ включаю `BROWSER_ANCHOR_VIA_SEARCH` в прод-контейнере не задан → действует код-дефолт `"domclick"`. Расширять список на Авито без отдельного замера не буду — ровно как написано в комментарии у константы. ### База для сравнения (снята ДО правки) `avito_detail_backfill`, доля блоков от попыток по суткам: | сутки | прогонов | попыток | обогащено | блоков | доля блоков | |---|---:|---:|---:|---:|---:| | 25.08 | 8 | 228 | 111 | 107 | 46.9% | | 26.08 | 8 | 89 | 23 | 66 | 74.2% | | 27.08 | 10 | 56 | 1 | 54 | 96.4% | | 28.08 | 11 | 189 | 55 | 132 | 69.8% | | 29.08 | 8 | 658 | 306 | 348 | 52.9% | | 30.08 (3 прогона) | 3 | 138 | 51 | 86 | 62.3% | Все прогоны без исключения заканчиваются `banned` по ratio-критерию, `ban_kind=platform`. Сравнивать после выката буду по **доле блоков от попыток** и по обогащению за сутки, а НЕ по доле прогонов со статусом `banned`: критерий обрыва срабатывает всегда, и статус про площадку ничего не говорит (уже разбиралось при калибровке #3184). ### Побочное наблюдение В логах Авито заметная доля отказов — `NS_ERROR_PROXY_BAD_GATEWAY` и `NS_ERROR_ABORT`, то есть отказ прокси, а не площадки. В `counters` они, судя по всему, попадают в общий счётчик блоков и завышают «долю блоков площадки». Отдельно не чинил, но при чтении цифр это стоит держать в уме. ### Дальше PR на тёплый контекст + origin/referer для detail-бэкфилла Авито. Хранилище сессий и авторизованные куки (#3179 / #3180) — отдельно, эта правка их не заменяет и не блокирует.
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#3251
No description provided.