fix(tradein): маркер полноты — encryptedPhones ИЛИ redirectPhones (#3191)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 13s
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 / 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 5m21s
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 13s
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 / 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 5m21s
Ревью #3364. Требуя именно encryptedPhones, отбраковывали бы вечно необмеренный класс карточек «без телефона / только чат»: в очередь они возвращаются, а ключ не появится. redirectPhones измерен тем же замером #3192 и присутствует в обеих ветках (с куками и без). Текст ABORT: consecutive_none смешанный (фетч-ошибка + parse-None + недогруз) — «N подряд без обогащения», а не «недогруженных».
This commit is contained in:
parent
4b5f8fb54c
commit
78e3da6bc3
4 changed files with 31 additions and 9 deletions
|
|
@ -1010,7 +1010,7 @@ class Settings(BaseSettings):
|
|||
# ── Порог полноты detail-страницы Яндекса (#3191) ────────────────────────
|
||||
# Полная карточка оффера — 3-5 МБ; недорендеренная приходит с HTTP 200, валидным
|
||||
# HTML и БЕЗ блока контактов (наблюдалось 1,8 МБ). Размер — второй признак к
|
||||
# структурному (scraper_kit...yandex.detail.DETAIL_CONTACTS_MARKER); любой из двух
|
||||
# структурному (scraper_kit...yandex.detail.DETAIL_CONTACTS_MARKERS); любой из двух
|
||||
# даёт отказ, объявление остаётся в очереди (detail_enriched_at не проставляется).
|
||||
# ENV: YANDEX_DETAIL_MIN_HTML_BYTES.
|
||||
yandex_detail_min_html_bytes: int = 1_000_000
|
||||
|
|
|
|||
|
|
@ -467,8 +467,10 @@ async def run_yandex_detail_backfill(
|
|||
)
|
||||
if consecutive_none >= max_consecutive_blocks:
|
||||
logger.error(
|
||||
# consecutive_none смешанный (фетч-ошибка + parse-None +
|
||||
# недогруз) — «недогруженных» назвало бы только один вклад.
|
||||
"yandex_detail_backfill: run_id=%d ABORT -- %d подряд "
|
||||
"недогруженных страниц. enriched=%d attempted=%d",
|
||||
"без обогащения. enriched=%d attempted=%d",
|
||||
run_id,
|
||||
consecutive_none,
|
||||
counters.enriched,
|
||||
|
|
|
|||
|
|
@ -140,3 +140,19 @@ def test_reason_names_the_two_signals() -> None:
|
|||
# Размерный: контакты есть, а страница обрезана.
|
||||
reason = detail_incomplete_reason(f'"{CONTACTS_MARKER}":[]', min_html_bytes=1_000_000)
|
||||
assert reason is not None and "недогружена" in reason
|
||||
|
||||
|
||||
def test_redirect_phones_alone_counts_as_complete() -> None:
|
||||
"""Карточка «без телефона / только чат»: redirectPhones есть, encryptedPhones нет.
|
||||
|
||||
Класс в замер #3192 не попадал (там у всех 12 были оба ключа). Требуя именно
|
||||
encryptedPhones, мы браковали бы такие карточки вечно — они возвращаются в очередь,
|
||||
а ключ у них не появится. Маркеры литералами: правку снимут — тест обязан краснеть
|
||||
по значению («карточка отбракована»), а не по ImportError.
|
||||
"""
|
||||
from scraper_kit.providers.yandex.detail import detail_incomplete_reason
|
||||
|
||||
body = "<html>" + "x" * 3_920_119
|
||||
assert detail_incomplete_reason(body + '"redirectPhones":["a"]</html>') is None
|
||||
# Фальсификация: без ОБОИХ ключей та же страница полного размера — недогруз.
|
||||
assert detail_incomplete_reason(body + "</html>") is not None
|
||||
|
|
|
|||
|
|
@ -50,11 +50,14 @@ logger = logging.getLogger(__name__)
|
|||
# offer 52275656 3 920 119 б encryptedPhones 65
|
||||
# offer 62983459 1 805 556 б encryptedPhones 0 <- недогруз
|
||||
# offer 12108408 4 732 884 б encryptedPhones 65
|
||||
# Ключ выбран так, чтобы он был у ПОЛНЫХ карточек в том же режиме, в каком мы ходим:
|
||||
# `encryptedPhones` отдаётся и анонимной сессии (app/services/yandex_session.py и
|
||||
# миграция 274 — с куками и без есть encryptedPhones + redirectPhones, отличается
|
||||
# только mainPhone, поэтому mainPhone признаком полноты быть не может).
|
||||
DETAIL_CONTACTS_MARKER = "encryptedPhones"
|
||||
# Ключи выбраны так, чтобы они были у ПОЛНЫХ карточек в том же режиме, в каком мы ходим:
|
||||
# оба отдаются и анонимной сессии (app/services/yandex_session.py и миграция 274 — с
|
||||
# куками и без есть encryptedPhones + redirectPhones, отличается только mainPhone,
|
||||
# поэтому mainPhone признаком полноты быть не может).
|
||||
# Достаточно ЛЮБОГО из двух: замером #3192 покрыты 12 карточек, у всех были оба ключа,
|
||||
# но класс «без телефона / только чат» в замер не попал. Требуя encryptedPhones, мы
|
||||
# браковали бы такие карточки ВЕЧНО (в очередь они возвращаются, а ключ не появится).
|
||||
DETAIL_CONTACTS_MARKERS = ("encryptedPhones", "redirectPhones")
|
||||
|
||||
# Второй, независимый признак. Полная карточка — 3-5 МБ; порог держим заметно ниже
|
||||
# наблюдавшегося недогруза (1,8 МБ), потому что размер зависит от объявления. Он ловит
|
||||
|
|
@ -74,8 +77,9 @@ def detail_incomplete_reason(
|
|||
"""
|
||||
if not html:
|
||||
return "empty html"
|
||||
if DETAIL_CONTACTS_MARKER not in html:
|
||||
return f"нет блока контактов ({DETAIL_CONTACTS_MARKER} отсутствует), {len(html)} б"
|
||||
if not any(marker in html for marker in DETAIL_CONTACTS_MARKERS):
|
||||
markers = "/".join(DETAIL_CONTACTS_MARKERS)
|
||||
return f"нет блока контактов ({markers} отсутствуют), {len(html)} б"
|
||||
if len(html) < min_html_bytes:
|
||||
return f"страница недогружена: {len(html)} б < {min_html_bytes} б"
|
||||
return None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue