gendesign/tradein-mvp/packages/scraper-kit/src/scraper_kit
bot-backend bf3214b9e4
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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 / browser-tests (pull_request) Successful in 1m7s
CI Trade-In / backend-tests (pull_request) Successful in 4m57s
fix(tradein/scrapers): диагноз блока брался из текстовых маркеров чужой площадки, а не из HTTP-статуса (#3196)
Сайдкар вообще не читал код ответа page.goto: страница классифицировалась
только по маркерам, снятым с Авито. Домклик отдаёт статическую `403 | Домклик`
на 26 624 байта, где нет ни одного такого маркера (замер прода 28.08.2026) —
она уезжала наверх как валидный HTML, парсер не находил состояние, и прогон
получал блок неизвестной природы. За 14 дней все 14 прогонов домклика легли с
ban_kind='unknown'; у Яндекса счётчика blocked не было вовсе, поэтому ветка
перевода прогона в 'banned' была недостижима по построению — ноль банов.

- browser/server.py: статус целевой навигации сохраняется per-provider и
  доезжает в тело /fetch аддитивным ключом "status" (ключ "html" не тронут);
  403/429 с маркерами челленджа больше не ждут PoW — ждать нечего, статическая
  страница сама себя не перезагрузит. Наверх идёт BanPageDetectedError, а не
  заглушка: вернув её контентом, воскресили бы #3045.
- scraper_kit/browser_fetcher.py: BrowserFetcher.last_response_status +
  ban_kind_from_status (403/429 → platform, 5xx → infra, прочее → None).
  Поток управления не менялся: fetch() по-прежнему отдаёт str.
- domclick: DomClickBlockedError несёт .status — один тип исключения на
  маркер-детект и на сбой фетча разводится без размножения типов; прогон
  передаёт перепись диагнозов в mark_backfill_finished.
- yandex: появился счётчик blocked, оживляющий ветку бана. Серии блоков и
  промахов парсера считаются РАЗДЕЛЬНО: иначе четыре промаха плюс один 403
  пятым давали 'banned' с переписью {platform: 1}.
- cian: ban_kinds наполняется только диагностируемым статусом. HTTP 200 с
  пустым разбором — дрейф разметки на нашей стороне, а не отказ площадки;
  записав его блоком, мы бы штамповали фиктивные баны у здорового источника
  (13 done против 1 banned за 14 дней).

Инвариант: непустой ban_kinds ⟺ виден ответ 403/429/5xx. Значения остаются в
пределах CHECK scrape_runs.ban_kind.

Известный пробел: шов providers/domclick/detail.py `blocked.status = status`
тестами не покрыт — существующие домкликовые тесты подают исключение готовым
моком и боевой fetch_detail не исполняют.
2026-08-28 23:21:54 +03:00
..
orchestration Merge pull request 'fix(tradein/domclick): исчерпание пула прокси помечалось как отказ сбора (#3118)' (#3174) from fix/3118-domclick-no-proxy into main 2026-08-27 22:03:56 +00:00
pricing refactor(scraper-kit): unify price bisection engine across providers + dedup (#2134) 2026-07-02 16:41:04 +00:00
providers fix(tradein/scrapers): диагноз блока брался из текстовых маркеров чужой площадки, а не из HTTP-статуса (#3196) 2026-08-28 23:21:54 +03:00
__init__.py feat(scraper-kit): copy core layer (base/save_listings/transport) with protocol injection, strangler (#2132) 2026-07-02 15:43:15 +00:00
avito_exceptions.py fix(tradein/scraper-kit): actualize avito fingerprint - impersonate/Sec-Fetch-Site/referer/cookie-check 2026-08-21 17:02:53 +03:00
base.py feat(tradein/matching): region_code у houses — вывод, а не выдумка (#3051 п.4) 2026-08-27 13:51:48 +05:00
browser_fetcher.py fix(tradein/scrapers): диагноз блока брался из текстовых маркеров чужой площадки, а не из HTTP-статуса (#3196) 2026-08-28 23:21:54 +03:00
ceiling_height.py fix(tradein): свести высоту потолков к одной колонке ceiling_height_m (#2779) 2026-08-07 09:18:48 +00:00
cian_exceptions.py fix(tradein/cian): 403 снимает узел с выдачи, а не гаснет в return None (#2700) (#2821) 2026-08-10 11:29:19 +00:00
cian_state_parser.py fix(tradein/cian): extract_all_states — discover new .concat() format, not just legacy .push() (#2438) 2026-07-04 21:03:32 +00:00
contracts.py feat(tradein/matching): region_code у houses — вывод, а не выдумка (#3051 п.4) 2026-08-27 13:51:48 +05:00
domclick_exceptions.py fix(tradein/scrapers): диагноз блока брался из текстовых маркеров чужой площадки, а не из HTTP-статуса (#3196) 2026-08-28 23:21:54 +03:00
geo.py feat(tradein/scraper): per-city sweep capability для 5 городов области (schedules disabled) 2026-07-12 20:06:46 +03:00
house_type_normalizer.py fix(tradein/houses): camelCase-типы домов приводятся к канону у источника (#2678) (#2719) 2026-08-06 09:55:54 +00:00
offer_price_history.py fix(tradein/scraper-kit): клампить diff_percent перед INSERT offer_price_history (#2404) 2026-07-04 10:44:26 +00:00
price_brackets.py feat(tradein/scraper): per-city sweep capability для 5 городов области (schedules disabled) 2026-07-12 20:06:46 +03:00
proxy_errors.py fix(tradein/proxy): доводить сигнал бана площадки до пула (#2600 п.1) (#2653) 2026-08-05 11:37:35 +00:00
py.typed chore(scraper-kit): scaffold internal package + uv workspace, build-safe (#2128) 2026-07-02 14:06:07 +00:00
repair_state_normalizer.py feat(scraper-kit): copy core layer (base/save_listings/transport) with protocol injection, strangler (#2132) 2026-07-02 15:43:15 +00:00
snapshot_writer.py fix(tradein/scrapers): метка наблюдения — время строки, а не старта транзакции (#2731) (#2742) 2026-08-06 16:19:56 +00:00
yandex_helpers.py fix(tradein/yandex): просмотры режутся по разделителю тысяч + Циан молчит о непонятой фразе (#2669) (#2773) 2026-08-07 08:44:48 +00:00