Назад к статьям

Парсинг динамических сайтов с Selenium и Python

Привет! Сегодня поговорим о том, как парсить сайты, которые ведут себя как капризные подростки — постоянно меняются, загружают контент через JavaScript и вообще не хотят отдавать данные просто так. Но мы-то знаем, как с ними договориться! 🚀

Почему обычный requests не работает?

Знакомо? Открываешь сайт в браузере — всё видно. Пытаешься спарсить через requests — получаешь пустую страницу или HTML без нужных данных. В чём подвох?

Дело в том, что многие современные сайты используют JavaScript для динамической загрузки контента. Когда ты делаешь обычный GET-запрос, сервер отдаёт только "скелет" страницы, а весь контент подгружается потом через JS. Вот тут-то и нужен Selenium — он умеет управлять настоящим браузером!

Устанавливаем всё необходимое

Для начала установим Selenium и драйвер для браузера. Я рекомендую Chrome, но можно и Firefox — дело вкуса.

# Установка через pip pip install selenium # Для автоматического управления драйверами pip install webdriver-manager

Первый скрипт: "Привет, мир!" парсинга

Давай напишем простой скрипт, который откроет страницу и подождёт, пока загрузится контент:

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service import time # Настройка драйвера (webdriver-manager сам скачает нужную версию) service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) try: # Открываем страницу driver.get("https://example.com") # Ждём, пока загрузится нужный элемент (максимум 10 секунд) element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, "h1")) ) # Получаем текст print(element.text) finally: driver.quit() # Важно! Закрываем браузер

Ждём, ждём, ждём... Или как не сойти с ума

Самая частая ошибка новичков — пытаться сразу получить данные, не дождавшись загрузки. Selenium работает быстрее, чем JavaScript на странице, поэтому нужно использовать ожидания (waits).

# Плохо: сразу пытаемся получить элемент title = driver.find_element(By.TAG_NAME, "h1") # Может упасть! # Хорошо: ждём появления элемента title = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.TAG_NAME, "h1")) )

Реальный пример: парсим новости

Давай напишем скрипт, который парсит заголовки новостей с сайта, где контент загружается динамически:

from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) try: driver.get("https://example-news-site.com") # Ждём загрузки списка новостей WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.CLASS_NAME, "news-item")) ) # Прокручиваем страницу вниз, чтобы загрузились все новости driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) # Даём время на подгрузку # Находим все заголовки news_items = driver.find_elements(By.CLASS_NAME, "news-item") for item in news_items: title = item.find_element(By.TAG_NAME, "h2").text link = item.find_element(By.TAG_NAME, "a").get_attribute("href") print(f"{title}: {link}") finally: driver.quit()

Полезные фишки

1. Headless режим (без окна браузера)

Если не хочешь видеть, как открывается браузер (и работать быстрее):

from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless') # Работает без окна options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') driver = webdriver.Chrome(service=service, options=options)

2. Ожидание загрузки JavaScript

Иногда нужно дождаться, пока JavaScript полностью выполнится:

# Ждём, пока document.readyState станет 'complete' WebDriverWait(driver, 10).until( lambda d: d.execute_script('return document.readyState') == 'complete' )

3. Обработка ошибок

Всегда обрабатывай исключения — сайты могут быть недоступны или изменить структуру:

try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "content")) ) except TimeoutException: print("Элемент не загрузился за 10 секунд") except Exception as e: print(f"Что-то пошло не так: {e}")

Итоги

Selenium — это мощный инструмент для парсинга динамических сайтов. Главное помнить:

  • Всегда используй ожидания (waits) вместо time.sleep()
  • Закрывай браузер через driver.quit()
  • Обрабатывай исключения
  • Используй headless режим для продакшена

Удачи в парсинге! Если что-то не работает — не расстраивайся, это нормально. Даже опытные разработчики тратят часы на отладку скриптов. Главное — не сдаваться! 💪