Парсинг Авито через прокси: почему сбор цен встаёт на 4-й минуте
05.10.26
Только открытые объявления и цены. Темп, лимиты Авито и настройка A-Parser.

Пару сотен страниц Авито отдаст и одному адресу. Дальше без прокси для парсинга Авито сбор встаёт. С одного адреса площадка отдаёт выдачу недолго, потом отвечает кодом 429 или страницей «Доступ ограничен: проблема с IP». В этой статье разбираю один сценарий: сбор открытых объявлений и цен для аналитики. Средняя цена по категории, разброс, сколько предложений появилось за неделю, как быстро уходят позиции дешевле рынка. Регистрации аккаунтов, рассылок, накрутки просмотров и любых обходов правил площадки здесь нет.
Первый сборщик под Авито я запустил на 10 потоков без пауз, по одной категории примерно в 12 000 объявлений. На 4-й минуте половина ответов была 403. Сбор встал. Адреса оказались ни при чём: за 4 минуты я сам отправил столько запросов, сколько живой посетитель не сделает за месяц, и площадка ответила ровно так, как должна отвечать на такую нагрузку.
Что брать из выдачи и чего не трогать
Для аналитики цен хватает того, что видно в выдаче категории без входа в аккаунт. В каждую карточку ходить обычно не нужно: цена, заголовок и дата уже стоят в списке, а переход в карточки умножает число запросов на количество объявлений на странице. Один запрос на страницу, и в нём уже десятки цен. Это первое, что снижает нагрузку и на площадку, и на ваш пул.
Поля, которые я сохраняю:
ID объявления, по нему склеиваются снятия разных дней и отсекаются дубли;
заголовок и категория;
цена в том виде, как её показывает выдача;
дата публикации;
местоположение, как оно указано в объявлении;
ссылка на объявление;
время снятия, своё, для истории.
Телефоны продавцов, переписку и профили пользователей не собираю. Для анализа цен они не нужны.
Для отчёта по категории я беру медиану. Среднее искажают объявления с ценой 1 рубль и заглушки вида 999 999, поэтому нижние и верхние 5 процентов цен отбрасываю до расчёта, а поднятые объявления с уже известным ID новыми не считаю.
Ещё одна мелочь, которая экономит часы. Сохраняйте сырой HTML первых 3 страниц каждого прогона. Когда через месяц разбор вдруг начнёт отдавать пустые цены, вы сравните старую и новую разметку за минуту и не будете гадать, что поменялось на площадке.
Как Авито ограничивает частые запросы
Первым срабатывает счётчик запросов на адрес. Пока темп похож на человека, выдача идёт. Когда с одного IP за короткое время уходят десятки страниц, приходит один из ответов:
429 Too Many Requests. Лимит запросов. Пауза обычно его снимает.
403 и страница «Доступ ограничен: проблема с IP». Адрес попал в блок, и ждать минуту бесполезно: уберите его из работы на несколько часов.
Бывает и третий вариант. Сервер отвечает 200, и внутри на месте выдачи лежит заглушка или страница проверки. Поэтому успешный ответ я проверяю по содержимому страницы, по коду его не определить. Расшифровка остальных кодов есть в статье ошибка прокси-сервера: коды и что делать.
Точных цифр лимита площадка не публикует. Они меняются. Рабочий темп я подбираю замером на своей задаче. Цифры из чужих статей переношу к себе только после такого замера, потому что у соседа другая категория, другое время суток и другое число потоков.

Темп: считаю от объёма
Возьмём категорию, где 300 страниц выдачи, и снимать её нужно раз в сутки. На каждый поток ставлю случайную паузу 4-9 секунд между запросами, в среднем 6,5 секунды, плюс около 1,5 секунды на ответ. Получается 8 секунд на страницу. Три потока проходят 300 страниц за 300 × 8 / 3 = 800 секунд, примерно 13 минут. Для суточной аналитики запас огромный.
Суточный прогон удобно разбить на заходы по 100 страниц с перерывом в 20-30 минут между ними. Сбор растягивается примерно на час, нагрузка ложится небольшими волнами, и любой сбой виден на маленьком куске, который легко перезапустить отдельно без повторного прохода по всей категории.
Частый вопрос: зачем 3 потока, когда можно поставить 50 и закончить за минуту. Затем, что площадка видит волну одинаковых запросов к одной категории, даже если каждый уходит с нового адреса. Ротация снимает лимит на один IP. Общую нагрузку на сайт она не отменяет, и держать её умеренной ваша задача.
Правила повторов у меня такие:
На 429 пауза 30-60 секунд, потом повтор с другого адреса. Если сервер прислал заголовок Retry-After, жду столько, сколько он просит.
На 403 адрес уходит из ротации на несколько часов, страница повторяется с другого.
После 5 неудачных попыток на одной странице поток её пропускает и пишет в лог.
Если доля 403 и 429 за 10 минут выше 5 процентов, число потоков режу вдвое.
В лог на каждый запрос пишу 5 полей: время, номер страницы, адрес выхода, код ответа и длину тела. По длине заглушка видна сразу, нормальная страница выдачи в разы тяжелее. По адресу выхода видно, не застрял ли поток на одном IP.
Куки между адресами не переношу. Сессия, которая за минуту сменила 8 IP, выглядит страннее, чем 8 разных посетителей без истории. Общие принципы сбора с ротацией собраны в статье прокси для парсинга.
Настройка в A-Parser
Для выдачи Авито подходит универсальный пар сер Net::HTTP. Ключевые настройки задания:
Request delay: 4,9. A-Parser понимает диапазон и берёт случайную паузу от 4 до 9 секунд.
Request retries: по умолчанию 10, я ставлю 5. Каждая попытка уходит с другого адреса.
Check content: регулярное выражение, которое находит признак нормальной выдачи, например блок с ценой. Не нашлось, и A-Parser загрузит страницу заново с другого адреса. Эта опция ловит заглушки с кодом 200.
Check next page: регулярное выражение на ссылку следующей страницы, чтобы пройти пагинацию в пределах лимита страниц.
Use proxy: включено.
Потоки: 3-5 на задание.

Прокси A-Parser читает из файла proxy.txt в папке проксичекера, по одной строке на адрес. При авторизации по логину формат строки login:password@ip:port, и в настройках проксичекера включается авторизация прокси. При доступе по IP логин не нужен, хватает ip:port. Список, который вы уже проверили сами, можно не гонять через проверку A-Parser: для этого есть опция No check proxies.
Отдельно про шлюз с ротацией. Если в proxy.txt одна строка, включите Reuse proxy between retries. Без этой опции A-Parser подбирает для каждой попытки другую строку из списка, и одной строки ему не хватит. Адрес выхода при ротации всё равно меняется на каждом запросе, так что повтор уйдёт с нового IP.
Перед полным прогоном я запускаю задание на 20 страниц в 1 поток и читаю лог. Сколько попыток ушло на страницу, сколько раз сработала Check content, какие коды пришли. Если на 20 страниц ушло больше 25 попыток, темп завышен или маркер выдачи подобран неудачно. Поднимать потоки рано.
Свой скрипт на Python
Если A-Parser не нужен, хватает requests и нескольких строк логики повторов:
import random, time, requests
PROXY = "http://LOGIN:PASS@IP:PORT"
PROXIES = {"http": PROXY, "https": PROXY}
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
MARKER = "кусок разметки нормальной выдачи"
def fetch(url, tries=5):
for n in range(tries):
try:
r = requests.get(url, headers=HEADERS, proxies=PROXIES, timeout=20)
except requests.RequestException:
time.sleep(10)
continue
if r.status_code == 200 and MARKER in r.text:
return r.text
ra = r.headers.get("Retry-After", "")
wait = int(ra) if ra.isdigit() else 30 * (n + 1)
time.sleep(wait + random.uniform(1, 5))
return None
for page in range(1, 301):
html = fetch(f"https://www.avito.ru/ПУТЬ_КАТЕГОРИИ?p={page}")
# разбор html и запись в базу
time.sleep(random.uniform(4, 9))Сессия здесь намеренно не используется: каждый запрос уходит без куки, и при ротации адрес у него свой. Если прокси с ротацией, адрес выхода меняется на каждом запросе на стороне пула, и в коде переключать ничего не нужно. Если у вас список адресов, берите их по кругу через itertools.cycle. Маркер вы находите сами в исходнике страницы списка. Классы в разметке площадки меняются после обновлений, поэтому маркер и селекторы держите в отдельном конфиге и ставьте оповещение на прогон, где цена пустая больше чем у 10 процентов объявлений. Пустые цены на таком прогоне значат новую разметку. Блок тут ни при чём.
Результат пишу в SQLite: одна строка на объявление в каждом снятии, с ID, ценой и временем. Через месяц такой таблицы видно, сколько живёт объявление в категории, на сколько продавцы снижают цену перед снятием с продажи и какая доля предложений висит дольше 30 дней.
Прокси для парсинга Авито: ротация и умеренная нагрузка
Блоки на сборе снимаются двумя вещами одновременно: темпом, похожим на живого посетителя, и адресами, которые меняются на каждом запросе, так что ни на один IP не ложится больше пары страниц подряд. Одно без другого не работает. Пул без пауз упрётся в общий лимит, паузы на одном адресе растянут сбор на сутки.
У WinGate прокси для Авито идут с автоматической ротацией: каждый запрос получает новый приватный IPv4, трафик безлимитный, потоков до 5000, хотя для этой задачи хватает 3-5 на задание. Подключение по IP или строкой IP:PORT:LOGIN:PASS, п ротоколы HTTP, HTTPS и SOCKS5. Для a-parser есть отдельная страница с настройкой, а для своего кода пригодится разбор, как устроен парсинг сайта на python через прокси.
Свой темп проверьте на живой категории до того, как купить прокси для авито: пул открывается на бесплатный тест до 2 часов. Этого хватает, чтобы снять 300 страниц трижды и посмотреть в логе долю 403 и 429 при ваших паузах.
Ориентир, что связка настроена верно: прогон укладывается во время из расчёта, доля 403 и 429 в логе держится на уровне единиц процентов, а пустых цен в базе нет. Тогда можно добавлять категории.
Свежие статьи
