Настройка прокси для мониторинга цен конкурентов
Пошаговое руководство по настройке прокси для мониторинга цен: ротация IP, geo-targeting, sticky-сессии, обход антибот-защит. Код на Python и bash.
Команда InfraProxy
13 апреля 2026 г.
Почему мониторинг цен ломается без прокси
Мониторинг цен конкурентов — одна из базовых задач e-commerce. Но маркетплейсы и интернет-магазины активно защищаются от автоматического сбора: rate-limiting, CAPTCHA, блокировка по IP, гео-зависимые цены.
Без правильно настроенных прокси система мониторинга деградирует: сначала появляются пустые ответы, потом блокировки, потом — неверные данные (сайт отдаёт другие цены для заблокированных IP). Результат — бизнес-решения на основе мусора.
В этом руководстве — конкретная настройка прокси для стабильного мониторинга цен. Не теория, а рабочие конфигурации и код.
Архитектура: как прокси встраиваются в пайплайн мониторинга
Типичный пайплайн мониторинга цен состоит из четырёх компонентов:
- Планировщик — определяет, какие URL и когда проверять
- Краулер — выполняет запросы через прокси
- Парсер — извлекает цены из HTML/JSON
- Хранилище — сохраняет данные для анализа
Прокси работают на уровне краулера. Правильная конфигурация определяет, будут ли запросы успешными.
Планировщик → [URL Queue] → Краулер → [Proxy Pool] → Целевой сайт
↓
Парсер → [Price DB] → Дашборд
Подробнее о построении полного инструмента — в нашей статье «Как построить инструмент мониторинга цен». Здесь сфокусируемся на прокси-части.
Шаг 1: Выбор типа прокси для мониторинга цен
Не все прокси одинаково подходят для ценового мониторинга. Выбор зависит от целевых сайтов.
| Характеристика | Datacenter | ISP Static | Residential (rotating) | |---------------|-----------|-----------|----------------------| | Скорость | До 1 Gbps | 100–500 Mbps | 10–50 Mbps | | Стоимость | Низкая | Средняя | Высокая | | Блокировки на маркетплейсах | Средние | Низкие | Минимальные | | Стабильность IP | Постоянный | Постоянный | Меняется | | Подходит для | Открытые каталоги, API | Маркетплейсы, магазины | Антибот-защита |
Рекомендации по типу сайта
- Открытые каталоги (без антибот-защиты): datacenter прокси — максимальная скорость, минимальная стоимость
- Маркетплейсы (Ozon, Wildberries, Amazon): ISP static — баланс скорости и успешности
- Сайты с агрессивным антиботом (Cloudflare Enterprise, Akamai): residential или ISP + fingerprint
Подробнее о различиях — в нашем сравнении datacenter и residential прокси.
Шаг 2: Настройка пула прокси
Базовая ротация через InfraProxy
import asyncio
import aiohttp
import random
from typing import Optional
class PriceMonitorProxy:
"""Менеджер прокси для мониторинга цен"""
def __init__(self, proxy_host: str, proxy_port: int,
username: str, password: str,
protocol: str = "socks5"):
self.base_url = f"{protocol}://{username}:{password}@{proxy_host}:{proxy_port}"
self.stats = {"success": 0, "failed": 0, "blocked": 0}
async def fetch_price(self, session: aiohttp.ClientSession,
url: str, retries: int = 3) -> Optional[str]:
"""Получить HTML страницы через прокси с ретраями"""
for attempt in range(retries):
try:
async with session.get(
url,
proxy=self.base_url,
timeout=aiohttp.ClientTimeout(total=20),
headers=self._get_headers()
) as resp:
if resp.status == 200:
self.stats["success"] += 1
return await resp.text()
elif resp.status == 403:
self.stats["blocked"] += 1
await asyncio.sleep(2 ** attempt)
else:
self.stats["failed"] += 1
except (aiohttp.ClientError, asyncio.TimeoutError):
self.stats["failed"] += 1
await asyncio.sleep(1)
return None
def _get_headers(self) -> dict:
"""Ротация User-Agent для естественного профиля"""
agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4) AppleWebKit/605.1.15 Safari/605.1.15",
"Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0",
]
return {
"User-Agent": random.choice(agents),
"Accept": "text/html,application/xhtml+xml",
"Accept-Language": "ru-RU,ru;q=0.9,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br",
}
def get_stats(self) -> dict:
total = self.stats["success"] + self.stats["failed"] + self.stats["blocked"]
return {
**self.stats,
"total": total,
"success_rate": f"{self.stats['success'] / max(total, 1) * 100:.1f}%"
}
Sticky-сессии для многостраничных каталогов
Некоторые сайты показывают разные цены в зависимости от «сессии» пользователя. Если IP меняется между страницами каталога, вы получите несогласованные данные. Решение — sticky-сессии.
import hashlib
def get_sticky_proxy(base_proxy: str, site_domain: str,
duration_minutes: int = 10) -> str:
"""Генерация sticky-прокси для конкретного сайта.
Один и тот же IP будет использоваться для всех запросов
к данному домену в течение duration_minutes.
"""
session_id = hashlib.md5(
f"{site_domain}:{duration_minutes}".encode()
).hexdigest()[:12]
# Формат InfraProxy: добавляем session-ID в URL
# socks5://user-session-abc123:pass@dc.infraproxy.ru:1080
parts = base_proxy.split("://")
protocol = parts[0]
auth_host = parts[1]
user, rest = auth_host.split(":", 1)
password, host_port = rest.rsplit("@", 1)
return f"{protocol}://{user}-session-{session_id}:{password}@{host_port}"
# Все запросы к ozon.ru пойдут через один IP в течение 10 минут
sticky = get_sticky_proxy(
"socks5://myuser:mypass@dc.infraproxy.ru:1080",
"ozon.ru"
)
Подробнее о стратегиях ротации — в нашей статье «Стратегии ротации прокси».
Шаг 3: Geo-targeting для региональных цен
Многие сайты показывают разные цены в зависимости от региона. Это нормальное поведение: доставка в Москву и Владивосток стоит по-разному, региональные скидки и акции различаются.
Почему geo-targeting критичен
Без привязки к региону вы получите:
- Среднюю цену, которая не соответствует ни одному реальному региону
- Ошибки в ценовой стратегии — вы думаете, что конкурент дешевле, а на самом деле дешевле только в Москве
- Упущенные региональные акции
Настройка в curl
#!/bin/bash
# Сбор цен с привязкой к региону
REGIONS=("moscow" "spb" "novosibirsk" "ekaterinburg")
PROXY_BASE="socks5://user:pass@dc.infraproxy.ru:1080"
for region in "${REGIONS[@]}"; do
echo "=== Регион: $region ==="
# Через InfraProxy: выбор гео через параметр в URL
# Формат: user-country-RU-city-moscow:pass@host:port
PROXY="socks5://user-country-RU-city-${region}:pass@dc.infraproxy.ru:1080"
curl -s --proxy "$PROXY" \
-H "Accept-Language: ru-RU,ru;q=0.9" \
-o "prices_${region}.html" \
"https://example-shop.ru/catalog/electronics"
echo "Сохранено: prices_${region}.html"
sleep 2 # пауза между регионами
done
Шаг 4: Rate-limiting и scheduling
Агрессивный краулинг — верный путь к блокировке. Правильный rate-limiting увеличивает success rate и уменьшает расход прокси.
Расчёт оптимальной скорости
| Тип сайта | Безопасный RPS | С прокси-ротацией | |-----------|--------------|-------------------| | Малый магазин | 1–2 req/s | 5–10 req/s | | Средний маркетплейс | 0.5–1 req/s | 10–30 req/s | | Крупный маркетплейс (антибот) | 0.2–0.5 req/s | 5–15 req/s | | API (с ключом) | По документации | По документации |
Правило: с пулом 100 000+ IP (InfraProxy) на каждый IP приходится 1 запрос в 10–60 секунд при параллельности 100–500. Этого достаточно, чтобы не вызывать подозрений.
Планировщик с адаптивным rate-limiting
import asyncio
import time
from collections import deque
class AdaptiveRateLimiter:
"""Адаптивный rate-limiter: замедляется при блокировках,
ускоряется при стабильной работе"""
def __init__(self, initial_rps: float = 5.0,
min_rps: float = 0.5, max_rps: float = 50.0):
self.current_rps = initial_rps
self.min_rps = min_rps
self.max_rps = max_rps
self.window = deque(maxlen=100) # последние 100 запросов
self._lock = asyncio.Lock()
async def acquire(self):
"""Ожидание перед следующим запросом"""
async with self._lock:
delay = 1.0 / self.current_rps
await asyncio.sleep(delay)
def report_result(self, success: bool):
"""Сообщить результат запроса для адаптации"""
self.window.append(success)
if len(self.window) < 20:
return
success_rate = sum(self.window) / len(self.window)
if success_rate > 0.95:
# Всё хорошо — можно ускориться на 10%
self.current_rps = min(
self.current_rps * 1.1, self.max_rps
)
elif success_rate < 0.8:
# Много блокировок — замедляемся вдвое
self.current_rps = max(
self.current_rps * 0.5, self.min_rps
)
# Использование
limiter = AdaptiveRateLimiter(initial_rps=10)
async def monitored_fetch(proxy_manager, url):
await limiter.acquire()
result = await proxy_manager.fetch_price(session, url)
limiter.report_result(result is not None)
return result
Шаг 5: Обработка антибот-защит
Маркетплейсы используют несколько уровней защиты. Вот как справляться с каждым.
JavaScript-рендеринг
Некоторые цены загружаются через JavaScript. Обычный HTTP-запрос вернёт пустую страницу.
from playwright.async_api import async_playwright
async def fetch_with_js(url: str, proxy_url: str) -> str:
"""Получить цену с JS-рендерингом через Playwright + прокси"""
async with async_playwright() as p:
# Парсим прокси URL
# socks5://user:pass@host:port
parts = proxy_url.replace("socks5://", "").split("@")
auth = parts[0].split(":")
server_parts = parts[1].split(":")
browser = await p.chromium.launch(
proxy={
"server": f"socks5://{parts[1]}",
"username": auth[0],
"password": auth[1]
},
headless=True
)
page = await browser.new_page()
await page.goto(url, wait_until="networkidle")
# Ждём появления элемента с ценой
await page.wait_for_selector(
"[data-price], .price, .product-price",
timeout=10000
)
content = await page.content()
await browser.close()
return content
CAPTCHA
При появлении CAPTCHA — не пытайтесь решать её автоматически на каждый запрос. Лучше:
- Сменить IP (ротация прокси)
- Увеличить задержку между запросами
- Проверить fingerprint (User-Agent, заголовки)
Подробнее о методах обхода антибот-защит — в нашей статье «Антибот-системы 2026».
Шаг 6: Мониторинг здоровья прокси
Прокси-пул — живая система. IP блокируются, разблокируются, скорость меняется. Без мониторинга вы узнаете о проблемах, когда данные уже устарели.
Метрики для отслеживания
import json
import time
from datetime import datetime
class ProxyHealthMonitor:
"""Мониторинг состояния прокси в реальном времени"""
def __init__(self):
self.metrics = {
"requests_total": 0,
"requests_success": 0,
"requests_blocked": 0,
"requests_timeout": 0,
"avg_latency_ms": 0,
"unique_ips_used": set(),
"started_at": datetime.now().isoformat()
}
self._latencies = []
def record(self, status: str, latency_ms: float,
proxy_ip: str = ""):
self.metrics["requests_total"] += 1
if status == "success":
self.metrics["requests_success"] += 1
elif status == "blocked":
self.metrics["requests_blocked"] += 1
elif status == "timeout":
self.metrics["requests_timeout"] += 1
self._latencies.append(latency_ms)
if proxy_ip:
self.metrics["unique_ips_used"].add(proxy_ip)
def report(self) -> dict:
total = self.metrics["requests_total"]
if total == 0:
return {"status": "no data"}
return {
"total_requests": total,
"success_rate": f"{self.metrics['requests_success'] / total * 100:.1f}%",
"block_rate": f"{self.metrics['requests_blocked'] / total * 100:.1f}%",
"timeout_rate": f"{self.metrics['requests_timeout'] / total * 100:.1f}%",
"avg_latency_ms": round(
sum(self._latencies) / len(self._latencies)
),
"p95_latency_ms": round(
sorted(self._latencies)[int(len(self._latencies) * 0.95)]
),
"unique_ips": len(self.metrics["unique_ips_used"]),
}
# Алерт, если success rate падает ниже 90%
monitor = ProxyHealthMonitor()
# ... после серии запросов:
report = monitor.report()
if float(report["success_rate"].rstrip("%")) < 90:
print(f"ALERT: Success rate {report['success_rate']} — проверьте прокси")
Полный пример: мониторинг каталога
Собираем всё вместе — рабочий скрипт мониторинга цен:
#!/bin/bash
# Быстрый мониторинг цен через curl + SOCKS5 прокси
PROXY="socks5://user:pass@dc.infraproxy.ru:1080"
URLS_FILE="target_urls.txt"
OUTPUT_DIR="prices/$(date +%Y-%m-%d)"
mkdir -p "$OUTPUT_DIR"
SUCCESS=0
FAILED=0
while IFS= read -r url; do
FILENAME=$(echo "$url" | md5sum | cut -c1-12)
HTTP_CODE=$(curl -s -o "$OUTPUT_DIR/${FILENAME}.html" \
-w "%{http_code}" \
--proxy "$PROXY" \
--connect-timeout 10 \
--max-time 20 \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0" \
-H "Accept-Language: ru-RU,ru;q=0.9" \
"$url" 2>/dev/null)
if [ "$HTTP_CODE" = "200" ]; then
((SUCCESS++))
else
((FAILED++))
echo "FAIL [$HTTP_CODE]: $url"
fi
# Случайная задержка 1-3 секунды
sleep $(( RANDOM % 3 + 1 ))
done < "$URLS_FILE"
echo "Готово: $SUCCESS успешных, $FAILED неудачных из $(wc -l < $URLS_FILE) URL"
Чек-лист настройки
Перед запуском мониторинга убедитесь:
- [ ] Выбран тип прокси под целевые сайты (DC/ISP/residential)
- [ ] Настроена ротация IP с пулом не менее 10 000 адресов
- [ ] Sticky-сессии включены для многостраничных каталогов
- [ ] Geo-targeting настроен для региональных цен
- [ ] Rate-limiting адаптивный (замедление при блокировках)
- [ ] User-Agent и заголовки ротируются
- [ ] Мониторинг success rate настроен + алерты
- [ ] Ретраи с экспоненциальной задержкой
Итог
Настройка прокси для мониторинга цен — это не «вставить прокси-URL в requests.get()». Это инженерная задача с несколькими измерениями: тип прокси, ротация, geo-targeting, rate-limiting, обработка антиботов и мониторинг здоровья.
С правильной настройкой пул из 100 000+ datacenter IP обеспечивает стабильный мониторинг десятков тысяч товаров ежедневно при success rate > 95%.
Для задач ценовой разведки в B2B также рекомендуем прочитать наше руководство по конкурентной разведке — там описана общая стратегия за пределами технической настройки.
Попробуйте InfraProxy для мониторинга цен — 100 000+ IP, SOCKS5/HTTP, пропускная способность до 1 Gbps, тестовый доступ за 1 рабочий день. Оставить заявку →
Нужны надёжные прокси для вашего проекта?
InfraProxy предоставляет серверные и резидентные прокси для российского бизнеса. Договор, постоплата, техподдержка.
Читайте также
Как настроить прокси для RAG-пайплайна
Практическое руководство по настройке прокси для RAG-пайплайна: архитектура, код на Python, sticky-сессии, расписание обходов. InfraProxy, SOCKS5, 100 000+ IP.
РуководстваNo-code веб-скрейпинг: извлечение данных без программирования
Как настроить сбор данных в 2026 году без написания кода: API для скрейпинга, extract_rules, автоматизация через n8n и Make.com, батчевая обработка 100+ страниц.
РуководстваПарсинг вакансий с авторизацией: логин через форму и sticky-сессии
Как собирать данные с площадок с вакансиями, требующих входа: авторизация через js_actions, session_id для сессий, extract_rules и хранение учётных данных.