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

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

В этой статье разберём парсинг динамических сайтов: когда контент подгружается через JavaScript, обычный requests не видит нужных данных. Покажем по шагам, как использовать Selenium, ждать загрузку и вытаскивать данные с примерами кода.

Когда нужен Selenium

Используйте Selenium, если страница в браузере показывает данные, а requests.get(url) возвращает HTML без них (пустой список, заглушки). Типичные случаи: лента, подгружаемая по скроллу, контент после нажатия кнопки, данные из API, вызываемого с страницы.

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

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

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

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

Установите Selenium и драйвер для браузера. Рекомендуем Chrome; драйвер можно подбирать вручную или через webdriver-manager. Документация: Selenium with Python.

# Установка через 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. Обработка ошибок

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

from selenium.common.exceptions import TimeoutException try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "content")) ) print(element.text) except TimeoutException: print("Элемент не загрузился за 10 секунд") except Exception as e: print(f"Ошибка: {e}") finally: driver.quit()

Итоги

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

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

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