Что такое парсинг и как работает парсер: 4 шага и код на Python
Ты открываешь карточку товара у конкурента, копируешь цену в таблицу, закрываешь вкладку и берёшься за следующую. На тридцатой карточке уже рябит в глазах. Что такое парсинг? Это та же работа, только делает её программа: сама открывает страницы, находит на них название, цену, наличие или отзывы и складывает всё в таблицу. Тебе остаётся открыть готовый файл.
Что такое парсинг простыми словами
Слово пришло из английского: parse значит «разбирать по частям». Открой любую страницу товара. Ты видишь фото, кнопку «В корзину» и цену крупным шрифтом. Программа видит длинный текст из тегов, классов и атрибутов, где цена спрятана где-то в середине. Парсинг и есть разбор этого текста: найти нужное место, достать значение и записать туда, где с ним удобно работать.
Что значит парсинг в разговоре продавцов и маркетологов? Обычно всю цепочку целиком. Если строго, работ там три. Краулер ходит по ссылкам и собирает адреса страниц. Скрейпер эти страницы скачивает. Парсер разбирает скачанное и вытаскивает данные. Когда тебе говорят «запусти парсер», имеют в виду все три сразу.
Есть ещё парсинг данных. Это тот же разбор с любым источником: прайс поставщика в Excel, выгрузка в XML, лог сервера, письмо с заказом. Парсинг сайтов из той же семьи, просто источник у него веб-страница.
Парсер что это такое: скрипт, программа или сервис
Парсер это программа, которая делает такой разбор. Встречается он в трёх видах. Скрипт на Python или JavaScript ты пишешь сам под конкретный сайт. Готовую программу ставишь на компьютер и настраиваешь сбор мышкой и шаблонами. Онлайн-сервису отдаёшь список ссылок и забираешь файл. Скрипт гибче всего, сервис быстрее всего запустить, программа где-то между ними.
Как работает парсер: запрос, ответ, разбор, сохранение
У любого парсера четыре шага, одинаковые и в самописном скрипте, и в программе с кнопками. Возьмём для примера одну карточку товара.
- Парсер отправляет сайту GET-запрос по ссылке на карточку, так же как браузер, когда ты жмёшь Enter в адресной строке. Вместе с запросом уходят заголовки: подпись программы User-Agent, язык, cookies.
- Сервер магазина отвечает: присылает код и тело страницы. Код 200 значит, что всё в порядке, 404 говорит, что такой карточки уже нет, а 403 и 429 означают отказ или просьбу сбавить темп.
- Из тела ответа парсер достаёт нужное по CSS-селектору или XPath. Звучит страшно, на деле это адрес элемента на странице, что-то вроде «текст из блока с классом price». Класс видно в Chrome: правый клик по цене, пункт «Просмотреть код».
- Найденное ложится строкой в CSV, таблицу или базу. Одна карточка даёт одну строку: ссылка, название, цена, наличие, время проверки.
Потом следующая ссылка и снова те же четыре шага. Сто карточек или сто тысяч, механика одна. Меняется только то, как сайт относится к такому потоку запросов.
Что такое парсинг JSON и почему с ним проще
Многие магазины и маркетплейсы отдают каталог в два приёма. Сначала приходит каркас страницы, потом браузер отдельным запросом догружает цены и остатки, и ответ на этот запрос приходит в JSON. Это текст, где данные уже разложены по полям вроде name, price и stock. Разбирать его проще, чем HTML: в Python хватает вызова r.json(), и цена лежит в своём поле, класс в вёрстке искать не нужно.
Найти такой запрос можно прямо в Chrome. Открой страницу каталога, нажми F12, перейди на вкладку Network и включи фильтр Fetch/XHR. Обнови страницу и пролистай список: запрос, в ответе которого видны цены, и есть нужный.
Как написать парсер на Python: короткий пример с прокси
Теперь руками. Скрипт ниже берёт ссылки на карточки из файла urls.txt, по каждой делает запрос через прокси, достаёт заголовок h1 и цену и пишет их в prices.csv. Сначала поставь библиотеки: pip install "requests[socks]" beautifulsoup4. Пакет beautifulsoup4 разбирает HTML, а приставка socks учит requests ходить через SOCKS5.
import csv
import random
import time
import requests
from bs4 import BeautifulSoup
PROXY = "socks5h://LOGIN:PASS@IP:PORT"
proxies = {"http": PROXY, "https": PROXY}
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Accept-Language": "ru-RU,ru;q=0.9"}
urls = open("urls.txt", encoding="utf-8").read().split()
with open("prices.csv", "w", newline="", encoding="utf-8") as out:
writer = csv.writer(out)
for url in urls:
time.sleep(random.uniform(1, 3))
r = requests.get(url, headers=headers, proxies=proxies, timeout=(5, 20))
if r.status_code != 200:
print(url, r.status_code)
continue
soup = BeautifulSoup(r.text, "html.parser")
name = soup.select_one("h1")
price = soup.select_one(".price")
if name and price:
writer.writerow([url, name.get_text(strip=True), price.get_text(strip=True)])
else:
print(url, "нет h1 или .price")Словарь headers нужен потому, что без него requests подписывается как python-requests, и сайт понимает, кто к нему пришёл, ещё до разбора страницы. timeout=(5, 20) даёт пять секунд на соединение и двадцать на ответ: без таймаута один зависший сайт подвесит весь цикл. Проверка status_code выводит в консоль каждую ссылку с кодом, отличным от 200, например 403 или 429, и пустые строки в таблицу не попадают. Пауза random.uniform(1, 3) ставит между запросами от одной до трёх секунд, чтобы ритм не выглядел как метроном. Класс .price здесь условный, у каждого магазина свой, подставь тот, что увидел через «Просмотреть код».
В строке PROXY умещается вся связка python прокси: схема, логин, пароль, адрес и порт. Схема socks5h отправляет через прокси ещё и DNS-запросы, со схемой socks5 имена сайтов разрешались бы на твоём компьютере. WinGate выдаёт доступ строкой IP:PORT:LOGIN:PASS, переставь её части в порядок из примера. Если в личном кабинете привязан твой IP, логин с паролем можно убрать, хватит socks5h://IP:PORT.
Парсинг цен с сайта в Гугл таблицу без кода
Код писать не хочешь? Для небольшого списка ссылок хватит Google Таблиц. Кладёшь ссылку на карточку в ячейку A2, в соседней пишешь =IMPORTXML(A2; "//h1"), и в ячейке появляется название товара. На место //h1 ставишь путь XPath к цене. Функция читает HTML, XML, CSV, TSV, RSS и Atom, а для таблиц и списков на странице есть соседняя IMPORTHTML.
Запрос при этом уходит с серверов Google, и ни паузу, ни заголовки, ни адрес задать нельзя. Проверить идею на нескольких карточках так удобно. Каталог конкурента на тысячи позиций собирают уже своим парсером.
Парсинг: для чего нужен магазину и продавцу
Где парсинг экономит часы, видно по обычным задачам магазина:
- Утром в таблице лежат цены конкурентов на те же товары, и ты решаешь, где снижать, где держать.
- Конкурент распродал позицию, которая есть у тебя, и ты узнаёшь об этом из отчёта без ручной проверки.
- Поставщик выкладывает товары на сайте и не даёт файла выгрузки: парсер переносит названия, характеристики и фото в таблицу для загрузки в твой каталог.
- Новые отзывы о твоих товарах с разных площадок собираются в одном месте, и на жалобу отвечаешь, пока покупатель ещё ждёт ответа.
- Из поисковых подсказок собирают запросы покупателей для описаний и заголовков карточек.
- Парсер проверяет и твою витрину: не съехала ли цена после акции, на месте ли фото.
Парсинг цен конкурентов и своих карточек
Типичная картина: в магазине несколько сотен товаров, и почти у каждого есть двойники у конкурентов. Раз в сутки парсер обходит эти ссылки и кладёт в таблицу строку: товар, продавец, цена, наличие. Дальше работает обычный фильтр: где ты дороже соседей, где дешевле, где у конкурента товар закончился.
На маркетплейсе одной цены мало. Покупатель видит цену со скидкой, зачёркнутую цену до скидки, срок доставки и рейтинг, и всё это тоже собирают в отдельные столбцы. Маркетплейсы часто догружают эти данные отдельным запросом, так что приём с вкладкой Network здесь пригодится сразу.
Что такое ошибка парсинга и откуда она берётся
Ошибка парсинга значит, что программа ждала данные в одном виде, получила в другом и разобрать их не смогла. Такая надпись бывает в скриптах, в готовых программах и в обычных приложениях, когда файл повреждён или записан в неожиданном формате. У парсера сайтов причин чаще всего три.
Первая: магазин обновил вёрстку. Класс price переименовали, селектор больше ничего не находит, и в таблице пустые ячейки. Вторая: в ответ пришла страница с капчей или сообщением об ограничении, и нужных полей в ней просто нет. Третья: ответ оборвался на середине или пришёл в другой кодировке, и JSON не читается. На все три случая хватает привычек: проверяй код ответа, пиши в журнал ссылки, где поле не нашлось, и иногда открывай пару карточек руками.
Защита от парсинга: как она работает на больших объёмах
Пока ты собираешь десяток карточек, сайт тебя почти не замечает. Сложности начинаются, когда запросов тысячи и все идут с одного компьютера. Магазин считает, сколько запросов пришло с одного IP за минуту, смотрит на подпись клиента и на ритм: человек листает с паузами, скрипт стучит ровно, как метроном.
- Перебрал лимит запросов на один адрес, и в ответ приходит 429 Too Many Requests, нередко вместе с заголовком Retry-After: там число секунд до следующей попытки.
- Адрес, с которого шёл поток, получает 403, и следующие запросы с него упираются в тот же отказ.
- Капчу показывают, когда поведение похоже на робота: ровный интервал, одна и та же подпись, сотни страниц подряд с одного адреса.
- Часть данных рисует JavaScript: requests получает каркас страницы, цена появляется уже в браузере, после выполнения скриптов.
Парсинг динамических сайтов, где цена грузится скриптом
С JavaScript два пути. Первый ты уже знаешь: найти во вкладке Network запрос, который приносит JSON, и повторять его напрямую. Так быстрее всего, и компьютер почти не нагружен. Второй путь: Playwright или Selenium. Они запускают настоящий браузер, ждут, пока страница догрузится, умеют нажать «Показать ещё» и прокрутить ленту. Playwright ставится двумя командами, pip install playwright и playwright install, вторая скачивает сами браузеры. Памяти браузер ест заметно больше голых запросов, поэтому на больших объёмах его оставляют для страниц, где без него никак.
Прокси для парсинга и раскладка запросов по адресам
Против лимита на адрес работают две вещи: паузы и число адресов. Паузу ты уже видел в коде. Адресов нужно много: поток делят между ними, и скрипт для каждой новой ссылки берёт следующий IP из списка. В коде выше для этого замени строку PROXY списком и бери адреса по кругу через itertools.cycle. Тогда каждый IP шлёт магазину немного запросов, сайт видит много разных посетителей, и каждый из них реже упирается в лимит и капчу.
Бесплатные списки из открытых источников для этого подходят плохо: через те же адреса до тебя гоняли чужие парсеры, многие не отвечают, часть давно сидит у сайтов в чёрных списках. У WinGate приватный пул IPv4 на ограниченный круг клиентов, и в публичные подборки эти адреса не выкладываются. Поэтому на них нет следа от толпы чужих парсеров из открытых списков.
Сколько стоит парсинг сайта и из чего складывается цена
Зависит от того, кто делает работу. Свой скрипт обходится в твоё время плюс адреса. Готовая программа чаще всего платная, и на больших объёмах ей тоже нужны прокси. Заказ у фрилансера или в сервисе оценивают по сайту: сколько страниц, как часто обновлять, есть ли защита и JavaScript, в каком виде отдать результат. Сайт поставщика с простыми карточками и выгрузкой раз в неделю стоит одних денег, маркетплейс с ежедневным обходом и капчей совсем других.
Адреса считай по потокам: трафик в WinGate безлимитный, и лишние тысячи карточек счёт не увеличат. Пример расчёта: парсер работает в 200 потоков, значит младший пакет на 1000 потоков закрывает его с запасом на рост. Если прямо сейчас решаешь, где прокси для парсинга купить под свой объём, сначала прогони urls.txt на бесплатном тесте до 2 часов и посчитай, на скольких ссылках сайт ответил кодом 200.
С чего начать сегодня: положи в urls.txt десять ссылок на карточки конкурента, найди через «Просмотреть код» класс цены, поставь его на место .price и запусти скрипт. В консоли пусто, в prices.csv десять строк? Значит, механика собрана, и можно добавлять ссылки.