gendesign/tradein-mvp/packages/scraper-kit/src/scraper_kit
bot-backend 0586951772
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m47s
feat(tradein/scraper): чекпоинт по якорям для avito_city_sweep (#3074)
Продолжение после yandex-свипа. Выбор источника — по замеру, а не «для
полноты»: за 60 дней avito_city_sweep дал 68 прогонов, 25 банов и 3 отмены
деплоем при среднем времени 15 мин и максимуме 97.

Прод-факт, который решает дело. Типичный итог свипа:

    {"anchors_done": 1, "anchors_total": 5, ...,
     "enrichment_abort_note": "detail enrichment aborted (Avito detail
      firewall/soft-block ...)"}

Прогон срывается блокировкой на ПЕРВОМ из пяти якорей. Без чекпоинта
следующий прогон снова идёт в первый якорь, упирается в ту же стену, и якоря
2-5 не собираются никогда.

Ключ чекпоинта — ИМЯ якоря, а не индекс: состав списка зависит от city_slug,
позиция в нём между городами не устойчива. По той же причине здесь не нужна
гарда по числу якорей, которая есть у combo-чекпоинта яндекса: там ключ
якоря не содержал, здесь якорь и есть ключ.

Инвариант, ради которого отдельный флаг _anchor_ok: в чекпоинт попадает
только якорь, пройденный до конца. Ветка блокировки делает return и до записи
не доходит, а generic-except доходит — якорь упал, но цикл продолжается.
Записать такой якорь пройденным значило бы, что следующий прогон пропустит
его навсегда, причём молча: прогон завершится штатно, просто часть города не
соберётся. Флаг сбрасывается на каждой итерации, иначе один упавший якорь
заразил бы все последующие.

Пропущенный якорь двигает anchors_done — чтобы счётчик продолжал означать
«докуда дошли по списку», а не «сколько собрал именно этот прогон».

domclick_city_sweep намеренно НЕ трогаю: 54 прогона, ноль отмен деплоем,
среднее время 3 минуты — чекпоинт там не окупается. cian_city_sweep (среднее
35 мин, 2 отмены) — следующий шард.

Тесты (4) поведенческие: якорь из чекпоинта не опрашивается вовсе; пройденный
дописывается поверх унаследованных; без чекпоинта обходятся все; упавший в
чекпоинт НЕ попадает. Оговорка: на исходном коде они падают по сигнатуре
(unexpected keyword argument), то есть доказывают отсутствие параметра, а не
поведение — поведенческую часть держат сами проверки. Весь набор #3074 —
10 passed.
2026-08-26 14:52:46 +03:00
..
orchestration feat(tradein/scraper): чекпоинт по якорям для avito_city_sweep (#3074) 2026-08-26 14:52:46 +03:00
pricing refactor(scraper-kit): unify price bisection engine across providers + dedup (#2134) 2026-07-02 16:41:04 +00:00
providers Merge pull request 'feat(tradein/yandex): is_pro_seller из агентского блока + бэкфилл (#3063 п.2)' (#3100) from fix/3063-pro-seller-derive into main 2026-08-26 07:55:37 +00: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 fix(scraper-kit): бедный re-scrape больше не стирает признаки продавца (#3067) 2026-08-23 21:52:38 +00:00
browser_fetcher.py fix(tradein/proxy): проба Домклика спрашивает защищённый путь, а не robots.txt (#2855) (#2856) 2026-08-13 06:02:38 +00: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 fix(tradein/matching): город развёртки доезжает до стража Tier-2a — межгородские склейки домов (#2777) (#2808) 2026-08-10 08:51:14 +00:00
domclick_exceptions.py fix(tradein/proxy): доводить сигнал бана площадки до пула (#2600 п.1) (#2653) 2026-08-05 11:37:35 +00: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