Amazon через IPv6 прокси: мониторинг цен и парсинг отзывов
Содержание
- Почему IPv4-пул умирает за сутки
- Как Amazon детектит парсеры в 2024-2025
- Ротация внутри /64: механика
- 3proxy config для прослушивания на всём /64
- /etc/3proxy/3proxy.cfg
- Что реально стоит проверить перед стартом
- Проверка MTU до Amazon через IPv6
- Если проходит — MTU 1500 OK. Если нет — уменьшайте -s до прохождения.
- Мониторинг цен: архитектура
- Извлечение цены: где ломается парсер
- Парсинг отзывов: пагинация и капча
- Сравнение типов прокси для Amazon
- Кейс: 5000 ASIN, три недели, что получилось
- Кейс: отзывы с авторизацией, что сломалось
- Кейс: MTU и «тихие» 0-байтные ответы
- Очередь и дедупликация: без них никак
- Юридическая сторона и ToS
- Чек-лист перед запуском
Парсинг Amazon — задача, где инфраструктура решает больше, чем сам парсер. Логика извлечения цены умещается в 30 строк, а вот чтобы эти 30 строк отработали 10000 раз без бана — нужен отдельный разговор. Разберём, как IPv6-прокси меняет правила игры, где грабли, и какие цифры реально получаются на выходе.
Почему IPv4-пул умирает за сутки
Классическая схема: берём датацентровый IPv4-прокси, крутим 50 потоков, собираем цены. Amazon отвечает 503 через 2-4 часа. Причина не в User-Agent и не в cookies — в плотности адресов. Один /24 содержит 256 адресов, и если ваш провайдер продаёт этот пул ещё десяти клиентам, Amazon видит кластер из 2560 запросов в минуту с одной подсети.
Система репутации IP у Amazon агрегирует сигналы по ASN и по /24. Даже свежий адрес из «чистого» пула получает пониженный trust score, если соседи уже наследили. Дальше — капча, потом 503, потом тихий бан на уровне TLS-фингерпринта.
IPv6 тут даёт структурное преимущество: провайдер выдаёт /64 на клиента, а это 2^64 адресов. Формально — 18 квинтиллионов. На практике ротация внутри /64 выглядит для антибота как обычный трафик с разных устройств одной сети. Amazon это понимает и относится к /64 мягче, чем к /24 с IPv4.
Как Amazon детектит парсеры в 2024-2025
Защита Amazon — это не один фильтр, а слоёный пирог. Нижний слой — IP-репутация и rate limiting по подсети. Средний — TLS fingerprint (JA3/JA4), HTTP/2 fingerprint, порядок заголовков, наличие `sec-ch-ua` при заявленном Chrome. Верхний — поведенческий: скорость навигации, паттерны кликов, отсутствие загрузки картинок и шрифтов.
Простой `requests` с подменённым UA палится на среднем слое мгновенно: JA3 хэш Python-urllib не совпадает с Chrome, а `Accept-Language: en-US,en;q=0.9` при отсутствии `sec-ch-ua-mobile` — красный флаг. `curl_cffi` с `impersonate="chrome120"` проходит средний слой, но упирается в поведенческий.
```python
from curl_cffi import requests
url = "https://www.amazon.com/dp/B0BDHWDR12"
headers = {
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
}
r = requests.get(
url,
headers=headers,
impersonate="chrome120",
proxies={
"http": "http://user:pass@[2a01:4f8:1c1e:8a3f::1]:8080",
"https": "http://user:pass@[2a01:4f8:1c1e:8a3f::1]:8080",
},
timeout=20,
)
print(r.status_code, len(r.text))
```
Обратите внимание на скобки вокруг IPv6-адреса в URL прокси. Без них `curl` и `requests` пытаются распарсить адрес как host:port и падают с `InvalidURL`. Это грабли №1, на которые наступают все.
Ротация внутри /64: механика
Провайдер выдаёт вам /64. Внутри него можно брать любой адрес — от `2a01:4f8:1c1e:8a3f::1` до `2a01:4f8:1c1e:8a3f:ffff:ffff:ffff:ffff`. Прокси-сервер (3proxy, Squid, HAProxy) слушает на всех или на конкретных адресах, а вы выбираете адрес на каждый запрос.
Ключевой момент: разные /64 — это разные сети с точки зрения Amazon. Разные адреса внутри одного /64 — это одна сеть. Поэтому ротация по адресам внутри /64 помогает от rate limiting, но не от репутации подсети. Если /64 уже «прожжён», меняйте /64 целиком.
```bash
3proxy config для прослушивания на всём /64
/etc/3proxy/3proxy.cfg
nserver 1.1.1.1
nscache 65536
timeouts 1 5 30 60 180 1800 15 60
auth strong
users parser:CL:secret
allow parser
proxy -6 -n -a -p8080 -i2a01:4f8:1c1e:8a3f::1
proxy -6 -n -a -p8081 -i2a01:4f8:1c1e:8a3f::2
proxy -6 -n -a -p8082 -i2a01:4f8:1c1e:8a3f::3
```
Для 256 адресов конфиг руками не пишут — генерируют скриптом. В проде обычно поднимают один прокси с `-i` на весь диапазон и управляют исходящим адресом через `SO_BINDTODEVICE` или параметры сессии.
Что реально стоит проверить перед стартом
Перед тем как запускать сбор цен, проверьте три вещи. Первое — что ваш /64 не в чёрных списках. Второе — что прокси не теряет IPv6-соединение на MTU. Третье — что DNS-резолвинг идёт через тот же адрес, что и HTTP-запрос, иначе Amazon увидит расхождение.
MTU — тихий убийца IPv6. Стандарт для Ethernet — 1500 байт, но туннели и некоторые провайдеры режут до 1280. Если прокси не умеет PMTUD (Path MTU Discovery), большие ответы Amazon (страницы товаров весят 800-1500 КБ) будут зависать на середине.
```bash
Проверка MTU до Amazon через IPv6
ping6 -c 4 -M do -s 1452 www.amazon.com
Если проходит — MTU 1500 OK. Если нет — уменьшайте -s до прохождения.
```
Разница между 1452 и 1400 байт в `-s` — это разница между рабочим парсером и потоком таймаутов. На практике провайдеры IPv6-прокси (в том числе lexic.ml, работающий с 2015 года) держат MTU 1500 и корректный PMTUD, но проверить перед покупкой лишним не будет.
Мониторинг цен: архитектура
Мониторинг — это не «спарсить страницу раз в час». Это система с очередью, дедупликацией и хранением истории. Наивный подход: 10000 ASIN, каждый час, 10000 запросов. Amazon заблокирует за час.
Рабочая схема: 10000 ASIN разбиваются на 10 шардов по 1000. Каждый шард обходится раз в 6 часов с рандомизацией ±30 минут. Итого — 10000 запросов за 6 часов, около 28 запросов в минуту. Это в пределах допустимого для одного /64 при правильной ротации.
```python
import asyncio
from curl_cffi.requests import AsyncSession
async def fetch_price(session, asin, proxy):
url = f"https://www.amazon.com/dp/{asin}"
try:
r = await session.get(url, proxies={"https": proxy}, timeout=15)
if r.status_code == 200:
return asin, extract_price(r.text)
return asin, None
except Exception as e:
return asin, str(e)
async def worker(queue, session, proxy_pool):
while True:
asin = await queue.get()
proxy = proxy_pool.pick()
result = await fetch_price(session, asin, proxy)
await save(result)
await asyncio.sleep(2 + random.uniform(0, 3))
queue.task_done()
async def main(asins):
queue = asyncio.Queue()
for a in asins:
queue.put_nowait(a)
async with AsyncSession(impersonate="chrome120") as s:
tasks = [worker(queue, s, pool) for _ in range(20)]
await asyncio.gather(*tasks)
```
Задержка 2-5 секунд между запросами с одного воркера — не паранойя. Amazon измеряет интервалы и палит «ровный» ритм. Рандомизация ±50% — минимально достаточная.
Извлечение цены: где ломается парсер
Цена на странице Amazon живёт в 4-6 разных местах в зависимости от региона, типа товара и наличия скидки. Селекторы меняются раз в 2-3 месяца. Хардкод `#priceblock_ourprice` не работает с 2021 года.
Рабочий подход — несколько селекторов с приоритетом плюс regex по JSON-LD. JSON-LD (`