feat(tradein/proxy_rotation): ротация IP через mobileproxy.space (aproxy.site) #3298

Merged
lekss361 merged 1 commit from feat/mobileproxy-rotation-provider into main 2026-08-31 11:01:42 +00:00
Owner

Summary

  • Пул за всю историю не сделал ни одной ротации: scrape_proxy_rotations пуста, rotate_proxy() жёстко привязан к хосту api.asocks.com, а купленные порты mobileproxy несут ссылки на aproxy.site и отвергались ещё до HTTP-вызова.
  • Диспетчеризация по хосту rotate_url. Путь ASocks не тронут: POST + Authorization: Bearer, лимит 3/сутки, обработка 401 — байт-в-байт как было.
  • Новый путь mobileproxy: GET с format=json, без заголовков авторизации — секрет (proxy_key) лежит в самом URL, отправлять туда токен ASocks нельзя. Успех признаётся по JSON status == "OK", а не по HTTP-коду.
  • new_ip пишется в scrape_proxies.exit_ip, rt отдаётся наружу как RotationResult.reconnect_delay_s.
  • Отдельный предохранитель MOBILEPROXY_DAILY_ROTATION_LIMIT = 200/сутки против асоксовых 3.

Зачем

Замер на живых портах: один IP держит 18-20 карточек Авито, дальше выход падает до нуля — четверти 100 / 44 / 0 / 0. С ротацией каждые 15 карточек обвал исчезает совсем: 91 / 64 / 73 / 83, итог 78% против 33%. Ротация — единственное, что это лечит, и до этого PR она была физически невозможна.

reconnect_delay_s нужен следующей задаче: сразу после смены IP канал ~2-12 с нерабочий, в замере две карточки подряд ушли в таймаут. Без ожидания по rt каждая ротация дарит два ложных «блока», а 14 из 20 прерывают прогон.

Test plan

  • pytest tests/services/test_proxy_rotation.py — 24 passed
  • pytest tests/services/test_proxy_pool.py — 56 passed (смежное, регрессий нет)
  • ruff check — чисто
  • Утечка proxy_key: не попадает в reason, note в scrape_proxy_rotations, тексты исключений и логи — есть отдельные тесты, где секрет намеренно вложен в текст исключения
  • Редиректы: httpx.AsyncClient создаётся без follow_redirects, дефолт httpx 0.28.1 — False; токен ASocks нельзя увести на чужой хост
  • Хост-пиннинг: changeip.mobileproxy.space по-прежнему отвергается (в прод-сети он и не резолвится)
  • CAST(:x AS type) во всех SQL, :x::type нет
  • code-reviewer: APPROVE, блокеров нет

Интеграция в скрапер-задачи (ротация по счётчику попыток, ожидание по rt, пересоздание контекста) — отдельным PR.

## Summary - Пул за всю историю не сделал **ни одной** ротации: `scrape_proxy_rotations` пуста, `rotate_proxy()` жёстко привязан к хосту `api.asocks.com`, а купленные порты mobileproxy несут ссылки на `aproxy.site` и отвергались ещё до HTTP-вызова. - Диспетчеризация по хосту `rotate_url`. Путь ASocks не тронут: POST + `Authorization: Bearer`, лимит 3/сутки, обработка 401 — байт-в-байт как было. - Новый путь mobileproxy: **GET** с `format=json`, **без заголовков авторизации** — секрет (`proxy_key`) лежит в самом URL, отправлять туда токен ASocks нельзя. Успех признаётся по JSON `status == "OK"`, а не по HTTP-коду. - `new_ip` пишется в `scrape_proxies.exit_ip`, `rt` отдаётся наружу как `RotationResult.reconnect_delay_s`. - Отдельный предохранитель `MOBILEPROXY_DAILY_ROTATION_LIMIT = 200/сутки` против асоксовых 3. ## Зачем Замер на живых портах: один IP держит **18-20 карточек** Авито, дальше выход падает до нуля — четверти `100 / 44 / 0 / 0`. С ротацией каждые 15 карточек обвал исчезает совсем: `91 / 64 / 73 / 83`, итог 78% против 33%. Ротация — единственное, что это лечит, и до этого PR она была физически невозможна. `reconnect_delay_s` нужен следующей задаче: сразу после смены IP канал ~2-12 с нерабочий, в замере две карточки подряд ушли в таймаут. Без ожидания по `rt` каждая ротация дарит два ложных «блока», а 14 из 20 прерывают прогон. ## Test plan - [x] `pytest tests/services/test_proxy_rotation.py` — 24 passed - [x] `pytest tests/services/test_proxy_pool.py` — 56 passed (смежное, регрессий нет) - [x] `ruff check` — чисто - [x] Утечка `proxy_key`: не попадает в `reason`, `note` в `scrape_proxy_rotations`, тексты исключений и логи — есть отдельные тесты, где секрет намеренно вложен в текст исключения - [x] Редиректы: `httpx.AsyncClient` создаётся без `follow_redirects`, дефолт httpx 0.28.1 — `False`; токен ASocks нельзя увести на чужой хост - [x] Хост-пиннинг: `changeip.mobileproxy.space` по-прежнему отвергается (в прод-сети он и не резолвится) - [x] `CAST(:x AS type)` во всех SQL, `:x::type` нет - [x] code-reviewer: ✅ APPROVE, блокеров нет Интеграция в скрапер-задачи (ротация по счётчику попыток, ожидание по `rt`, пересоздание контекста) — отдельным PR.
lekss361 added 1 commit 2026-08-31 10:40:19 +00:00
feat(tradein/proxy_rotation): ротация IP через mobileproxy.space (aproxy.site)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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 4m53s
4968144693
Пул за всю историю не сделал ни одной ротации: rotate_proxy() жёстко привязан к
хосту api.asocks.com, а три купленных порта mobileproxy несут ссылки на
aproxy.site и отвергались до HTTP-вызова. При этом замер показал, что ротация —
единственное, что снимает выгорание адреса: один IP держит 18-20 карточек Авито
(четверти 100/44/0/0), со сменой каждые 15 обвал исчезает совсем (91/64/73/83).

Диспетчеризация по хосту rotate_url. Путь ASocks не тронут (POST + Bearer,
лимит 3/сутки). Для aproxy.site — GET с format=json без заголовков авторизации:
секрет лежит в самом URL, отправлять туда токен ASocks нельзя. Успех признаётся
по JSON status==OK, а не по HTTP-коду. new_ip пишется в scrape_proxies.exit_ip,
rt отдаётся как RotationResult.reconnect_delay_s — следующей задаче он нужен,
чтобы выждать переподключение канала: замер показал, что сразу после смены IP
две карточки уходят в таймаут.

Отдельный предохранитель MOBILEPROXY_DAILY_ROTATION_LIMIT=200/сутки: кулдауна у
провайдера не обнаружено (13 ротаций подряд дали 13 уникальных адресов), потолок
нужен только против runaway-цикла.
lekss361 merged commit a256077211 into main 2026-08-31 11:01:42 +00:00
lekss361 deleted branch feat/mobileproxy-rotation-provider 2026-08-31 11:01:42 +00:00
Sign in to join this conversation.
No reviewers
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#3298
No description provided.