feat(tradein/browser): имитация чтения страницы человеком, целиком opt-in (#3283) #3308
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3308
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/3283f-sidecar-humanized-reading"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Зачем
У сайдкара не было ни одной строки имитации поведения: после
page.gotoшли толькоwait_for_timeoutиcontent().grep -n "scroll\|mouse\|wheel\|go_back" browser/server.py— ноль совпадений.Контракт
Новое необязательное поле тела
POST /fetch—behaviour:scrollcontent()dwell_ms[min, max]дополнительной случайной паузы; невалидное →400, как уfetch_modehop_recommendedreuse_context=TrueПоля нет → не исполняется ни одна новая строка.
Почему opt-in, а не «включить и радоваться»
Вклад поведения в выход не доказан. Замер 31.08 сравнивал «без ротации и без поведения» против «ротация + поведение» — две переменные сразу. Ротацию мы с тех пор выкатили отдельно, и сама по себе она выход не подняла: 53% блоков до неё, 52% после. Прежде чем включать поведение навсегда, надо померить его одно — а для этого дефолт обязан остаться прежним.
Отбор ссылок для hop — две ступени
CSS-селектор сужает раздел, шаблон URL отличает карточку от рубрики и футера. Без второй ступени
a[href]на карточке Авито увёл бы на главную, и след потерял бы смысл.a[href*="/kvartiry/"]+_\d{7,}(?:\?|$)— шаблон снят на живом замере 31.08.a[href*="/card/"]+/card/sale__flat__\d+— по логам сайдкара.Noneсужение не применяется, поведение прежнее.Джиттер пейсинга
BROWSER_PAGE_INTERVAL_JITTER_Sс дефолтом 0. В отличие от остального, пейсинг телом запроса не гейтится, поэтому ненулевой дефолт сломал бы ту же измеримость.uniform(0,0) == 0.0— интервал численно прежний, но крутилка (env) есть.Проверка
231 passed— набор сайдкара, запущенный как в CI (pytest + aiohttp, без backend-венва).Покрыто: отсутствие
behaviour→ ни прокрутки, ни dwell, ни хопа;scroll→ вызовыmouse.wheelв заданном диапазоне; 5 вариантов невалидногоdwell_msи невалидный типbehaviour→400; хоп только на свой хост; хоп не берёт рубрику того же хоста (вторая ступень); отказ хопа не ломает основной ответ; безreuse_contextхопа нет.Что дальше
Проводка со стороны таска (параметры расписания, разнообразие якорной выдачи) — отдельным PR, вместе с правкой порядка «ротация до бана».
У сайдкара не было ни одной строки имитации поведения: после page.goto шли только wait_for_timeout и content(). grep по scroll/mouse/wheel/go_back давал ноль совпадений. Новое НЕОБЯЗАТЕЛЬНОЕ поле тела POST /fetch — behaviour: scroll — 3-6 прокруток колесом с паузами 700-1800мс перед content(); dwell_ms — [min,max] дополнительной случайной паузы; hop_recommended — заход на ОДНУ соседнюю карточку того же хоста, результат наружу не идёт, отказ глотается, только при reuse_context. Поле отсутствует → не исполняется ни одна новая строка. Это осознанно: вклад поведения в выход НЕ доказан. Замер 31.08 сравнивал «без ротации и без поведения» против «ротация + поведение», то есть две переменные сразу; ротацию мы выкатили отдельно, и сама по себе она выход не подняла (53% блоков до, 52% после). Прежде чем включать поведение навсегда, его надо померить одно — а для этого дефолт обязан остаться прежним. Ссылки для hop отбираются в две ступени: CSS-селектор сужает раздел, шаблон URL отличает карточку от рубрики и футера. Без второй ступени "a[href]" на карточке Авито увёл бы на главную. Шаблон Авито (путь с /kvartiry/ и id из 7+ цифр) снят на живом замере 31.08; Домклик — /card/sale__flat__<id> по логам сайдкара. cian/yandex/generic шаблона не имеют осознанно: их вёрстку я не снимал, а выдуманный шаблон хуже отсутствующего — при None сужение не применяется. BROWSER_PAGE_INTERVAL_JITTER_S с дефолтом 0: джиттер пейсинга, в отличие от остального, телом запроса не гейтится, поэтому ненулевой дефолт сломал бы ту же измеримость. uniform(0,0)==0.0 — интервал численно прежний, но крутилка есть. Тесты сайдкара: 231 passed.