CoderCastrov logo
CoderCastrov
Наука о данных

Как парсить динамически генерируемые данные с помощью Python

Как парсить динамически генерируемые данные с помощью Python
просмотров
6 мин чтение
#Наука о данных

Как преодолеть преграду в виде JavaScript-кода

Содержание

1. Введение

**Вы когда-нибудь пытались спарсить данные с веб-страницы, которые остаются скрытыми до тех пор, пока пользователь не выполнит определенное действие, такое как прокрутка вниз или нажатие кнопки? **и ваш метод парсинга не может получить к ним доступ? Если да, то этот учебник для вас.

**Здесь вы узнаете технику скачивания динамически генерируемых данных. **Она состоит в использовании Scrapy, библиотеки, предназначенной для парсинга данных в большом масштабе, и Selenium, фреймворка, который имитирует поведение человека в браузере.

2. Предварительные требования

- Подготовка окружения

Сначала вам нужно создать новую среду. Используя conda, введите следующую команду в терминале.

conda create --name parser
conda activate parser

Вам также понадобятся библиотеки, о которых мы упоминали выше.

pip install Scrapy
pip install selenium

- Установка драйвера Chrome

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

https://www.google.com/chrome/

Также нам нужно установить драйвер Chrome по ссылке:

https://chromedriver.chromium.org/

3. Описание страницы

Страница, которую мы используем в качестве примера, продает продукты, связанные с видеоиграми:

https://www.microplay.cl/

На странице, при нажатии (колесиком) на категорию "VIDEOJUEGOS", мы переходим на страницу, где можем выбрать продукт для покупки.

Если вы нажмете на любой продукт, мы перейдем на страницу его покупки.

Где показано название, цена и описание. Мы собираем эти данные для всех продуктов.

4. Создание проекта

Для инициализации проекта необходимо выполнить следующие команды в терминале.

scrapy startproject scraper
touch scraper/scraper/spiders/spiders.py

Это создаст структуру, в которой мы будем изменять файлы, отмеченные звездочкой (*).

scraper
 ├── scraper
 │   ├── spiders
 │   │   ├── __init__.py
 │   │   └── spiders.py *
 │   ├── __init__.py
 │   ├── items.py *
 │   ├── middlewares.py
 │   ├── pipelines.py
 │   └── settings.py *
 └── scrapy.cfg

5. Парсинг URL-адресов товаров (Selenium)

Мы извлечем все URL-адреса товаров, а затем пропустим их через функцию, которая будет собирать данные.

В файле spiders.py импортируйте библиотеки Scrapy и Selenium. Создайте класс паука с параметром name и списком start_urls.

Пауки - это классы, которые определяют, как будет производиться парсинг определенного сайта (или группы сайтов). И это имя используется для идентификации каждого класса, если у вас есть более одного парсера.

Теперь на странице https://www.microplay.cl/productos/juegos, чтобы получить URL-адреса, нам нужно определить их XML-пути. Для этого щелкните правой кнопкой мыши на любом изображении товара и выберите "Инспектировать".

Это покажет нам HTML-код. Проверьте путь, который ведет к выбранному элементу. В нашем примере изображение соответствует тегу img, который находится внутри тега a.

Могут быть элементы с тем же путем, которые не имеют никакого отношения к товарам. Способ отличить их - выбрать тег с определенным классом, чтобы избежать выбора других элементов HTML.

В данном случае класс card__item внутри тега div повторяется 20 раз на странице, что соответствует 20 карточкам товаров, загруженным на экран.

Таким образом, XML-путь будет:

".//div[@class='card__item']/a"

У нас есть более 20 элементов в данной категории. Но остальные загружаются динамически, то есть есть JavaScript-функция, которая их загружает.

Если мы прокрутим страницу до конца, увидим кнопку "VER MÁS". Поэтому мы хотим имитировать действие пользователя, нажимая эту кнопку, чтобы получить остальные скрытые данные.

Для этого нам нужно получить XML-путь кнопки.

Он соответствует тегу img внутри тега a. Поскольку очень вероятно, что есть несколько элементов с тем же тегом, мы выбираем класс, который их отличает. В данном случае это класс load.

Убедитесь, что он появляется только в том элементе, который вам нужен.

XML-путь будет:

.//a[@class='load']

В файле spiders.py определите следующие переменные.

Внутри класса MicroplaySpider определите начальное значение для headless, чтобы браузер работал в фоновом режиме.

Создайте функцию, которая загружает все товары. Функция представляет собой цикл, который сначала нажимает на нужную кнопку с помощью

wait.until(EC.element_to_be_clickable((By.XPATH, self.btn_xpath)))

а после некоторого ожидания ищет следующую кнопку с помощью

driver.find_element_by_xpath(self.btn_xpath).click()

Цикл останавливается, когда больше не находит кнопок. На Python:

Также создайте функцию, которая собирает URL-адреса и отправляет их в парсер, который мы определим в следующем разделе. С помощью следующего кода

driver = Chrome(options=self.chrome_options)
wait = WebDriverWait(driver, 10)
driver.get(url)

он инициализирует драйвер, инициализирует ожидание и загружает URL-адрес в драйвер. С помощью

products = driver.find_elements(by=By.XPATH, value=self.card_xpath)for prod in products:
    prod_url = prod.get_attribute(“href”)
    yield scrapy.Request(prod_url)

мы получаем все URL-адреса и передаем их в парсер. На Python это выглядит так:

6. Парсинг одного продукта (Scrapy)

При нажатии на любой продукт, мы переходим на страницу покупки. Например:

https://www.microplay.cl/producto/audifono-over-ear-pro-g1-gamer-pokemon-otl/

Щелкнув правой кнопкой мыши и выбрав "Исследовать элемент", мы можем получить соответствующий тег.

В файле items.py сначала импортируем следующее.

Название принадлежит тегу h1. И мы идентифицируем его с помощью класса content__ficha внутри тега section. (Убедитесь, что оно появляется только один раз)

XML-путь будет:

".//section[contains(@class, 'content__ficha')]/h1/text()"

Теперь повторим для цены продукта.

cd scraper/scrapy crawl microplay -O data.csv

XML-путь для цены:

".//span[@class='text_web']/strong"

Для описания.

XML-путь для описания:

".//div[@id='box-descripcion']"

Затем мы получаем пути для всех данных, которые нам нужны. Внутри MicroplaySpider напишите функцию с именем parse. Она будет содержать загрузчик, который является классом предварительной обработки данных, который мы определим.

Обратите внимание, что мы собираем четыре характеристики: название, цена, URL и описание.

Чтобы создать класс ItemLoader, сначала импортируйте необходимые библиотеки в файл items.py.

С помощью загрузчика мы можем предварительно обрабатывать данные столько, сколько нам нужно. Рекомендуется использовать его только для очистки мусора, созданного страницей, то есть для удаления html-тегов, лишних пробелов или лишних символов.

Наконец, напишите класс, указав каждую функцию, по которой будут обрабатываться данные. Параметр

input_processor=MapCompose()

отвечает за компоновку набора функций, через которые будут проходить данные. И параметр

output_processor=TakeFirst()

соберет первый результат, который вернет парсер. На Python:

Мы почти готовы, осталось только настроить файл settings.py.

Внутри settings.py укажите директорию драйвера (она может отличаться для каждого компьютера).

Затем добавьте некоторую задержку, чтобы предотвратить загрузку слишком большого количества элементов одновременно.

Наконец, измените ограничение скорости, чтобы избежать перегрузки. Будьте вежливы к странице.


7. Завершенный код

- scraper/scrapers/spiders/spiders.py

- scraper/scrapers/items.py

- scraper/scrapers/settings.py

Для запуска парсера, внутри папки scraper, в терминале выполните следующую команду (это займет несколько минут для завершения выполнения):

scrapy crawl microplay -O data.csv

И это создаст файл .csv, содержащий данные.

8. Заключение

Теперь вы знаете, как обойти стену кода JavaScript. Таким образом, у вас есть возможность парсить практически любую страницу, которую вы хотите.

Удачи в парсинге 😊.