Selenium парсинг книг: сбор данных с Litres

В этой статье мы рассмотрим пример парсера на Selenium для сбора данных о книгах с сайта Litres. Скрипт автоматически загружает популярные книги, нажимая кнопку «Показать ещё», собирает информацию о названии, авторе, рейтинге, цене и ссылке, а затем сохраняет её в HTML-таблицу с красивым оформлением. Этот пример полезен для мониторинга книжных каталогов, анализа цен или создания персонализированных списков книг.

Для чего можно использовать этот пример?

Этот код подходит для следующих задач:

  • Мониторинг книжных каталогов: Сбор данных о популярных книгах, ценах и рейтингах.
  • Анализ данных: Извлечение информации для сравнения или исследований.
  • Создание отчётов: Генерация HTML-таблиц для удобного просмотра.
  • Обучение Selenium: Практика работы с динамическими страницами и пагинацией.

Необходимые инструменты

Для работы скрипта потребуется установить Python, библиотеки Selenium и WebDriver Manager. Selenium управляет браузером, а WebDriver Manager упрощает установку ChromeDriver.

Установка необходимых библиотек.

pip install selenium webdriver-manager

Основные модули и импорты Selenium для Python

Код программы

Ниже приведён полный код с подробными комментариями, который реализует сбор данных о книгах с сайта Litres, включая динамическую подгрузку контента и сохранение в HTML-таблицу.

Основной код программы для работы с Selenium

import time  # Импорт модуля time для создания пауз между действиями
from selenium import webdriver  # Импорт Selenium для управления браузером
from selenium.webdriver.common.by import By  # Модуль для поиска элементов по CSS/XPath
from selenium.webdriver.chrome.service import Service  # Класс для управления сервисом ChromeDriver
from selenium.webdriver.support.ui import WebDriverWait  # Модуль для явного ожидания
from selenium.webdriver.support import expected_conditions as EC  # Условия для ожидания
from webdriver_manager.chrome import ChromeDriverManager  # Автоматическая установка ChromeDriver

# Настройки скрипта
URL = "https://www.litres.ru/popular/"  # URL страницы с популярными книгами
MAX_LOADS = 5  # Максимальное количество нажатий на кнопку "Показать ещё"
DELAY = 3  # Задержка (в секундах) для загрузки контента

# Вывод информации о количестве нажатий
print(f"Будет выполнено максимум {MAX_LOADS} нажатий на кнопку 'Показать ещё'")

# Инициализация браузера Chrome
options = webdriver.ChromeOptions()  # Создание объекта для настройки браузера
options.add_argument("--start-maximized")  # Открытие браузера в полноэкранном режиме
# Автоматическая установка ChromeDriver через WebDriver Manager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
driver.get(URL)  # Открытие целевой страницы

# Создание объекта WebDriverWait для ожидания загрузки элементов
wait = WebDriverWait(driver, 10)

# Динамическая подгрузка книг через нажатие кнопки "Показать ещё"
for i in range(MAX_LOADS):
    try:
        # Ожидание, пока кнопка "Показать ещё" не станет кликабельной
        show_more_btn = wait.until(
            EC.element_to_be_clickable((By.XPATH, "//div[contains(text(), 'Показать ещё')]"))
        )
        # Прокрутка к кнопке для видимости
        driver.execute_script("arguments[0].scrollIntoView(true);", show_more_btn)
        time.sleep(1)  # Пауза для стабилизации
        show_more_btn.click()  # Клик по кнопке
        print(f"✅ Нажали 'Показать ещё' ({i+1})")
        time.sleep(DELAY)  # Ожидание загрузки нового контента
    except Exception:
        # Если кнопка не найдена или больше нет страниц, прерываем цикл
        print(f"❌ Кнопка 'Показать ещё' не найдена или больше нет страниц (после {i} нажатий)")
        break

# Сбор данных о книгах
books = driver.find_elements(By.CSS_SELECTOR, "div.ArtContent-module__vj10ya__wrapper")  # Поиск всех карточек книг
data = []  # Список для хранения данных
for book in books:
    try:
        # Извлечение названия книги
        title = book.find_element(By.CSS_SELECTOR, "a[data-testid='art__title']").text.strip()
    except:
        title = "N/A"  # Если название не найдено, используем заглушку

    try:
        # Извлечение имени автора
        author = book.find_element(By.CSS_SELECTOR, "a[data-testid='art__authorName--link']").text.strip()
    except:
        author = "N/A"  # Если автор не найден, используем заглушку

    try:
        # Извлечение рейтинга и количества оценок
        rating = book.find_element(By.CSS_SELECTOR, "span[data-testid='art__ratingAvg']").text.strip().replace(',', '.')
        votes = book.find_element(By.CSS_SELECTOR, "span[data-testid='art__ratingCount']").text.strip().replace(' ', '')
        rating_num = float(rating)  # Преобразование рейтинга в число
        votes_num = int(votes)  # Преобразование количества оценок в число
        rating_full = f"{rating} ({votes} оценок)"  # Форматированный текст рейтинга
    except:
        rating_num = 0.0  # Заглушка для рейтинга
        votes_num = 0  # Заглушка для оценок
        rating_full = "N/A"  # Если рейтинг не найден

    try:
        # Извлечение цены
        price = book.find_element(By.CSS_SELECTOR, "div[data-testid='art__finalPrice']").text.strip()
    except:
        price = "N/A"  # Если цена не найдена

    try:
        # Извлечение ссылки на книгу
        link = book.find_element(By.CSS_SELECTOR, "a[data-testid='art__title']").get_attribute("href")
    except:
        link = "N/A"  # Если ссылка не найдена

    # Добавление данных в список
    data.append([title, author, rating_full, price, link, rating_num, votes_num])

# Закрытие браузера
driver.quit()

# Сортировка данных по рейтингу и количеству оценок (в порядке убывания)
data_sorted = sorted(data, key=lambda x: (x[5], x[6]), reverse=True)

# Сохранение данных в HTML-файл с оформлением
html_file = "litres_books.html"
with open(html_file, "w", encoding="utf-8") as f:
    # Запись HTML-заголовка и стилей
    f.write('''<html>
<head>
    <meta charset="UTF-8">
    <title>Популярные книги Litres</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background-color: #f7f7f7; }
        h2 { color: #333; }
        table { border-collapse: collapse; width: 100%; background-color: #fff; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        th, td { border: 1px solid #ddd; padding: 10px; text-align: left; font-size: 14px; }
        th { background-color: #4CAF50; color: white; }
        tr:nth-child(even) { background-color: #f2f2f2; }
        tr:hover { background-color: #e0f7fa; }
        a { color: #2196F3; text-decoration: none; }
        a:hover { text-decoration: underline; }
        td.number { width: 50px; font-weight: bold; }
    </style>
</head>
<body>
    <h2>Популярные книги с Litres (отсортированы по рейтингу и количеству оценок)</h2>
    <table>
        <tr>
            <th>#</th>
            <th>Название</th>
            <th>Автор</th>
            <th>Рейтинг</th>
            <th>Цена</th>
            <th>Ссылка</th>
        </tr>
''')
    # Добавление данных в таблицу
    for idx, row in enumerate(data_sorted, start=1):
        f.write(f"<tr>")
        f.write(f"<td class='number'>{idx}</td>")
        f.write(f"<td>{row[0]}</td>")
        f.write(f"<td>{row[1]}</td>")
        f.write(f"<td>{row[2]}</td>")
        f.write(f"<td>{row[3]}</td>")
        f.write(f"<td><a href='{row[4]}' target='_blank'>Ссылка</a></td>")
        f.write(f"</tr>")
    # Завершение HTML
    f.write("</table></body></html>")

# Вывод сообщения об успешном сохранении
print(f"✅ Данные сохранены: {html_file}")

Результат

Как работает скрипт?

В этом примере скрипт Selenium выполняет следующие действия:

  • Инициализация браузера: Запуск Chrome с автоматической установкой драйвера.
  • Динамическая подгрузка: Нажатие кнопки «Показать ещё» для загрузки большего числа книг.
  • Сбор данных: Извлечение названия, автора, рейтинга, цены и ссылки для каждой книги.
  • Сортировка: Упорядочивание данных по рейтингу и количеству оценок.
  • Сохранение: Создание HTML-таблицы с красивым оформлением для просмотра.

Этот пример полезен для автоматизации сбора данных с книжных сайтов, анализа популярности книг и создания структурированных отчётов.

Больше примеров по парсингу на parsertools.ru/primers.