fix(tradein): sweep shared-session (SERP+detail) через mobile proxy (#623) (#805)
All checks were successful
Deploy Trade-In / test (push) Successful in 26s
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 34s
All checks were successful
Deploy Trade-In / test (push) Successful in 26s
Deploy Trade-In / build-backend (push) Successful in 42s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 34s
Co-authored-by: bot-backend <bot-backend@gendsgn.local> Co-committed-by: bot-backend <bot-backend@gendsgn.local>
This commit is contained in:
parent
a9e4aecb54
commit
950d0f60de
2 changed files with 35 additions and 0 deletions
|
|
@ -34,6 +34,7 @@ from curl_cffi.requests import AsyncSession
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.core.config import settings
|
||||||
from app.services import scrape_runs
|
from app.services import scrape_runs
|
||||||
from app.services.scrapers.avito import AvitoScraper
|
from app.services.scrapers.avito import AvitoScraper
|
||||||
from app.services.scrapers.avito_detail import fetch_detail, save_detail_enrichment
|
from app.services.scrapers.avito_detail import fetch_detail, save_detail_enrichment
|
||||||
|
|
@ -66,6 +67,19 @@ _CHROME_HEADERS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _avito_proxies() -> dict[str, str] | None:
|
||||||
|
"""#623: mobile-proxy egress для shared-сессии sweep'а.
|
||||||
|
|
||||||
|
КРИТИЧНО: sweep создаёт собственную shared AsyncSession и присваивает её
|
||||||
|
`scraper._cffi`, перезатирая проксированную сессию из `AvitoScraper.__aenter__`.
|
||||||
|
Через эту же сессию идёт и SERP, и detail-энричмент (fetch_detail). Без прокси
|
||||||
|
detail-страницы летят с datacenter-IP → HTTP 429 → весь run mark_banned.
|
||||||
|
Пусто (env не задан) → прямое подключение (dev/no-op).
|
||||||
|
"""
|
||||||
|
url = settings.avito_proxy_url
|
||||||
|
return {"http": url, "https": url} if url else None
|
||||||
|
|
||||||
|
|
||||||
# ── Result dataclasses ──────────────────────────────────────────
|
# ── Result dataclasses ──────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -133,6 +147,7 @@ async def run_avito_pipeline(
|
||||||
impersonate="chrome120",
|
impersonate="chrome120",
|
||||||
timeout=25,
|
timeout=25,
|
||||||
headers=_CHROME_HEADERS,
|
headers=_CHROME_HEADERS,
|
||||||
|
proxies=_avito_proxies(),
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -351,6 +366,7 @@ async def run_avito_city_sweep(
|
||||||
impersonate="chrome120",
|
impersonate="chrome120",
|
||||||
timeout=25,
|
timeout=25,
|
||||||
headers=_CHROME_HEADERS,
|
headers=_CHROME_HEADERS,
|
||||||
|
proxies=_avito_proxies(),
|
||||||
) as session:
|
) as session:
|
||||||
try:
|
try:
|
||||||
for idx, (lat, lon, name) in enumerate(_anchors, start=1):
|
for idx, (lat, lon, name) in enumerate(_anchors, start=1):
|
||||||
|
|
|
||||||
|
|
@ -411,3 +411,22 @@ async def test_fetch_around_blocked_when_rotation_exhausted(
|
||||||
await scraper.fetch_around(56.84, 60.60, 1000, pages=1)
|
await scraper.fetch_around(56.84, 60.60, 1000, pages=1)
|
||||||
|
|
||||||
assert rot.await_count == 1 # одна попытка ротации, потом сдаёмся
|
assert rot.await_count == 1 # одна попытка ротации, потом сдаёмся
|
||||||
|
|
||||||
|
|
||||||
|
# ── #623 sweep-pipeline proxy (SERP+detail через mobile proxy) ───
|
||||||
|
|
||||||
|
|
||||||
|
def test_avito_proxies_helper(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
"""_avito_proxies: None без env, dict {http,https} при заданном AVITO_PROXY_URL.
|
||||||
|
|
||||||
|
Регрессия: sweep создаёт shared-сессию, через неё идут и SERP, и detail —
|
||||||
|
без прокси detail летит с datacenter-IP → 429 → run banned (#623 followup).
|
||||||
|
"""
|
||||||
|
from app.services import scrape_pipeline as sp
|
||||||
|
|
||||||
|
monkeypatch.setattr(sp.settings, "avito_proxy_url", None)
|
||||||
|
assert sp._avito_proxies() is None
|
||||||
|
|
||||||
|
url = "http://u:p@mproxy.site:16928"
|
||||||
|
monkeypatch.setattr(sp.settings, "avito_proxy_url", url)
|
||||||
|
assert sp._avito_proxies() == {"http": url, "https": url}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue