Вы освоили машинное обучение, знаете, чем transformer отличается от LSTM, но где брать данные для своих проектов? Готовые датасеты — это хорошо, но они общие. А если вам нужны посты из конкретного Telegram‑канала, отзывы с узкопрофильного форума или корпус текстов по редкой теме?
Парсинг сайтов — это навык, который превращает интернет в вашу персональную фабрику данных. Без него даже самая умная модель останется без «топлива». В этой статье мы рассмотрим весь путь: от первого запроса к сайту до готового датасета, пригодного для обучения.
Мы будем двигаться от простого к сложному. Вы узнаете, как парсить статические страницы, обходить базовые блокировки и организовывать масштабный сбор данных.
? Прежде чем переходить к практике, пройдите короткий бесплатный тест по NLP и языковым трансформерным моделям. Он поможет понять, в каких темах вы уже уверены, а что стоит подтянуть. ➞ |
С чего всё начинается
Прежде чем писать код, нужно понять, как устроен веб. Представьте, что интернет — это огромная библиотека, а ваш браузер — библиотекарь, который ходит за книгами. Парсер — это робот‑библиотекарь, который делает это быстро и по заданному алгоритму.
Всё начинается с HTTP‑запроса. Когда вы вводите адрес сайта, ваш браузер отправляет серверу запрос: «Дай мне, пожалуйста, содержимое страницы». Сервер отвечает HTML‑кодом — это «скелет» страницы, размеченный тегами.
Пример простого HTML‑фрагмента:
<div class="product"> <h2>Название товара</h2> <span class="price">1000 ₽</span> <p class="description">Описание товара...</p> </div>
Парсер должен найти этот блок (div class="product") и извлечь из него нужные данные: заголовок (h2), цену (span.price) и описание (p.description).
GET и POST являются двумя основными типами запросов. GET используется для получения данных. Когда вы открываете страницу товара, браузер отправляет GET‑запрос. В свою очередь POST используется для отправки данных на сервер, например, при заполнении формы поиска или авторизации. На начальном этапе вам почти всегда будет достаточно GET‑запросов.
Requests + BeautifulSoup
Это стандартная связка для парсинга, известная как «золотая середина» для большинства задач, потому что requests скачивает страницу, а BeautifulSoup помогает находить в ней данные.
Почему они хороши вместе? Requests выступает в роли курьера, доставляя вам HTML‑код, а BeautifulSoup — в роли аналитика, который этот код изучает и находит в нём закономерности. requests идеально подходит для базовых HTTP‑операций, а BeautifulSoup — для навигации по HTML‑дереву и поиска элементов.
Для установки необходимо выполнить следующее:
pip install requests beautifulsoup4 lxml
Здесь lxml — это быстрый парсер, который мы передадим BeautifulSoup для ускорения работы. Теперь давайте напишем скрипт, который загружает страницу и извлекает заголовки статей.
import requests from bs4 import BeautifulSoup # 1. Отправляем GET-запрос к сайту url = "https://example.com/blog" # Для реальных проектов всегда указывайте User-Agent, чтобы не походить на бота headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } response = requests.get(url, headers=headers) # 2. Проверяем, успешно ли прошёл запрос (код 200 означает "OK") if response.status_code == 200: # 3. Передаём HTML-код страницы BeautifulSoup для анализа soup = BeautifulSoup(response.text, 'lxml') # 4. Находим все элементы, содержащие заголовки. # Предположим, заголовки статей находятся в теге <h2> с классом "post-title" titles = soup.find_all('h2', class_='post-title') # 5. Извлекаем и выводим текст из каждого найденного элемента for title in titles: print(title.text.strip()) else: print(f"Ошибка загрузки страницы. Код: {response.status_code}")
Краткий разбор полётов:
requests.get(url, headers=headers)загружает страницу.BeautifulSoup(response.text, 'lxml')создаёт объект, с которым удобно работать.soup.find_all('h2', class_='post-title')ищет все теги<h2>с классомpost-title. Это один из самых мощных методов библиотеки.title.text.strip()достаёт текст внутри тега и удаляет лишние пробелы и переносы строк.
Продвинутый поиск: CSS‑селекторы
Метод find_all — это конечно хорошо, но иногда удобнее использовать CSS‑селекторы. Это мощный язык запросов к элементам HTML. Давайте посмотрим несколько примеров использования.
|
Найдем все ссылки внутри элементов с классом «
|
|
Теперь поищем элемент с id=«
|
|
Найдем все изображения внутри блока с классом «
|
Метод .select() возвращает список всех подходящих элементов, а.select_one() — первый подходящий. Это делает код более читаемым, особенно при работе со сложной вложенностью.
Когда страницы оживают: Playwright для SPA и React‑сайтов
Современный интернет — это уже не просто набор HTML‑страниц. Многие сайты (особенно с технологиями React, Vue, Angular) — это одностраничные приложения (SPA). Они загружают пустой «скелет», а весь контент подтягивается скриптами уже после загрузки.
Вы можете получить HTML‑код такой страницы через requests, но красивого текста с данными в нём не будет. Вам нужен инструмент, который может не просто скачать файл, а запустить браузер и выполнить весь JavaScript‑код, как это делает обычный пользователь. И здесь на сцену выходит Playwright.
Playwright — это библиотека для автоматизации браузеров (Chrome, Firefox, Safari). Она запускает настоящее браузерное окно (или «голову», headless‑режим) и выполняет все действия, которые может делать человек: кликать, скроллить, вводить текст. После того как страница полностью загружена и все скрипты отработали, мы можем получить её финальный HTML‑код и спокойно распарсить его уже знакомым BeautifulSoup. Это незаменимый инструмент для сбора данных с SPA, сайтов с бесконечной прокруткой (infinite scroll) и для обхода несложной защиты от ботов.
Для установки выполним следующее:
|
|
Далее рассмотрим пример скрипта для динамической страницы:
import asyncio from playwright.async_api import async_playwright from bs4 import BeautifulSoup async def scrape_dynamic_site(): async with async_playwright() as p: # Запускаем браузер (headless=False, чтобы увидеть окно браузера) browser = await p.chromium.launch(headless=True) page = await browser.new_page() # Переходим на сайт и ждём, пока загрузится сеть (важно для SPA!) await page.goto("https://quotes.toscrape.com/scroll") await page.wait_for_load_state("networkidle") # Симулируем прокрутку вниз для подгрузки новых элементов (если нужно) for _ in range(3): await page.evaluate("window.scrollTo(0, document.body.scrollHeight)") await page.wait_for_timeout(1000) # Ждём подгрузки # Получаем HTML-код полностью отрисованной страницы html = await page.content() # Закрываем браузер await browser.close() # Теперь можно парсить этот HTML через BeautifulSoup soup = BeautifulSoup(html, 'lxml') quotes = soup.select('.quote') for quote in quotes: text = quote.select_one('.text').text author = quote.select_one('.author').text print(f"{author} said: {text[:50]}...") asyncio.run(scrape_dynamic_site())
В этом коде мы не просто скачиваем страницу, а эмулируем поведение пользователя: ждём загрузки, прокручиваем вниз, даём время подгрузиться новым элементам, и только потом забираем готовый HTML.
Пайплайн для качественного датасета
Получить сырой текст с сайта — это только полдела. Чтобы он превратился в полезный датасет для NLP, ему нужна обработка. Это похоже на добычу нефти: сначала идёт бурение (парсинг), а потом — сложная переработка (очистка), чтобы получить бензин (датасет).
Вот основные шаги по превращению «грязных» веб‑данных в пригодные для обучения модели:
Извлечение (Extraction): Мы уже это умеем. Получаем HTML и вытаскиваем из него нужные поля (текст, даты, теги).
Очистка (Cleaning): Удаляем HTML‑теги, которые могли остаться. Убираем мусор: специальные символы (
,\xa0,\u200b), лишние пробелы и переносы строк.Нормализация (Normalization): Приводим текст к единому виду. Например, все даты приводим к формату ГГГГ‑ММ‑ДД, имена и названия очищаем от случайных символов.
Предобработка для NLP (Preprocessing): Этот шаг зависит от вашей задачи. Он может включать:
Токенизацию (разбиение на слова).
Удаление стоп‑слов (очень частых слов, не несущих смысла: «и», «в», «на»).
Лемматизацию или стемминг (приведение слов к начальной форме: «бежал», «бежит», «бегут» → «бежать»).
Теперь давайте рассмотрим пример кода, который дополняет наш пайплайн, превращая сырой HTML в чистый текст.
import re import pandas as pd from bs4 import BeautifulSoup from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer # Не забудьте скачать ресурсы NLTK: nltk.download('stopwords'), nltk.download('wordnet') lemmatizer = WordNetLemmatizer() stop_words = set(stopwords.words('russian')) def clean_text(html_content): # 1. Извлечение текста из HTML soup = BeautifulSoup(html_content, 'lxml') text = soup.get_text(separator=' ') # 2. Приведение к нижнему регистру и удаление спецсимволов text = text.lower() text = re.sub(r'[^а-яa-z0-9\s]', '', text) # Оставляем только буквы, цифры и пробелы # 3. Токенизация (разбиение на слова) tokens = text.split() # 4. Удаление стоп-слов и коротких слов tokens = [token for token in tokens if token not in stop_words and len(token) > 2] # 5. Лемматизация tokens = [lemmatizer.lemmatize(token) for token in tokens] # 6. Сборка обратно в строку clean_text = ' '.join(tokens) return clean_text # Пример использования в вашем пайплайне raw_data = [] # список словарей, полученных после парсинга for item in raw_data: item['cleaned_content'] = clean_text(item['raw_html']) df = pd.DataFrame(raw_data) df.to_csv('my_dataset.csv', index=False) # Сохраняем готовый датасет
Следуя этому пайплайну, вы превратите ворох сырых HTML‑страниц в структурированный, чистый датасет, готовый для обучения моделей классификации, генерации текста или построения RAG‑систем.
Заключение
Парсинг сайтов — это фундаментальный навык для любого специалиста по данным, который хочет работать с реальными, неигрушечными задачами. Мы прошли путь от базовых HTTP‑запросов до запуска браузеров и очистки данных. Теперь у вас есть инструментарий, чтобы создавать собственные датасеты для самых смелых NLP‑проектов.

Когда нужно не просто «поиграться с LLM», а встроить языковые модели в реальный продукт, быстро выясняется: базового понимания ChatGPT уже недостаточно. Нужно разбираться, как работают трансформеры, embeddings, RAG, тонкая настройка моделей и оценка качества, иначе проект легко превращается в набор красивых демо без стабильного результата.
Курс «Языковые трансформенные модели / NLP» помогает перейти от поверхностного использования нейросетей к инженерному пониманию NLP‑систем: как выбирать подходящую архитектуру, готовить данные, работать с текстовыми корпусами и собирать решения, которые можно применять в рабочих задачах.
Если вы уже пробовали работать с LLM, но хотите перейти от промптов и демо к более инженерному пониманию моделей, начните с бесплатного открытого урока:
— 20 мая в 20:00. «Основы парсинга сайтов».
Разберём, как с помощью Python скачивать информацию с сайтов, извлекать нужные данные и собирать основу для собственного датасета, который затем можно использовать в NLP‑задачах.
Полный список бесплатных уроков мая смотрите в дайджесте.
Комментарии (2)

Emelian
07.05.2026 13:25Парсинг сайтов – это навык, который превращает интернет в вашу персональную фабрику данных. Без него даже самая умная модель останется без «топлива». В этой статье мы рассмотрим весь путь: от первого запроса к сайту до готового датасета, пригодного для обучения.
Естественно, без конкретных примеров! Зато с конкретной рекламой курсов.
Парсинг сайтов – это фундаментальный навык для любого специалиста по данным, который хочет работать с реальными, неигрушечными задачами. Мы прошли путь от базовых HTTP‑запросов до запуска браузеров и очистки данных.
Но, как мы этого достигли – мы вам, забесплатно, не расскажем?
Теперь у вас есть инструментарий, чтобы создавать собственные датасеты для самых смелых NLP‑проектов.
Не у нас, а у вас!
Чего явно не хватает статье, так это демонстрации результатов вашей технологии. Поэтому, проделаю за вас вашу работу, покажу, на примере полного парсинга онлайн-словаря, как извлекать данные словарных статей и примеров фраз из десятков тысяч загруженных html-страниц, для целей изучения иностранного языка. Попутно, продемонстрирую, в каком виде сохранять данные и как делать их очистку (не идеальную, но, вполне сносную!). Не благодарите! :)
Смотрите мою статью: «Запоминаем иностранные слова по видео-словарю, упорядоченного по грамматическим категориям и переводам» в https://habr.com/ru/articles/1021912/ .

Первая часть (из четырёх) словарной статьи для слова «aller».
ML_Football
Отличная статья. Особенно про Playwright — сам недавно через это прошёл, когда парсил Transfermarkt для своего ML-проекта.
У меня сайт оказался хитрее: просто подменить User-Agent и поставить таймауты оказалось недостаточно. Пришлось эмулировать поведение реального пользователя: случайные задержки, движение мыши (через pyautogui), и даже менять fingerprint браузера через playwright-stealth. Без этого бан летел после 50-60 запросов