Парсер товаров OZON из определенной категории



Простой парсер для демонстрации и проверки возможности обхода категории. Из карточки берется только артикул, название и цена, проверки на ошибки не используются, это все необходимо добавлять.

Общий принцип работы. Написан на Python, используются библиотеки BeautifulSoup и Selenium. Список категорий изначально сохраняется в текстовый файл для последовательного обхода. После открытия категории в отдельный список сохраняются ссылки на карточки товаров.

Далее в отдельном цикле запускается обход всех ссылок на товары, полученная информация добавляется в общий список, после завершения обхода создается новый файл JSON.

Далее код будет рассмотрен более подробно.

Из файла загружается список категорий и передается в переменную.

Запускается общий цикл для обхода категорий. Ссылка на текущую категорию передается в функцию.

Создает переменную для хранения собранных ссылок. Запускаем Google Chrome через Selenium. Название категории заносим в переменную, для удобства оно используется в дальнейшем для названия файла JSON.

Для обхода категории другие парсеры обычно используют схему: полная прокрутка до конца категории, после чего запускается сбор ссылок. У меня данный способ работал крайне нестабильно, поэтому принято решение пойти более грубым путем. После каждой каждой прокрутки на 1000 пикселей запуск сбора ссылок, дубли сразу убираются через множество. Для больших категорий явно не самый оптимальный метод. Как минимум, можно оптимизировать общую схему прокрутки/сбора. В данном случае используется цикл с условием по количеству собранных ссылок.

Создается переменная для сохранения информации из карточки товаров в виде списка. Далее запускается новый цикл, на каждой итерации очередная ссылка на товар передается в функцию. Возвращается подготовленный набор данных, который добавляется в общий список. После завершения список сохраняется в файл JSON.

Карточки открываются в новой вкладке.

Сбор информации со страницы товара. Для тестирования использовались разные способы. Артикул получен непосредственно средствами Selenium. Цена (текущая без карты ОЗОН) и название — через BeautifulSoup. Сохранение страницы в файл html оставлено для удобства тестирования, чтобы не получить бан от сайта за некорректные запросы.

Подготовка и отправка полученных данных, закрытие вкладки.

Полученный результат.

Код полностью

import json
import time
import undetected_chromedriver as uc 
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import time as tm
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By


with open("categories.txt", "r", encoding="utf-8") as file_cl:
    categories = file_cl.read().split('\n')


def get_products_links(category):
    products_urls = []  # список для хранения ссылок на карточки товаров
    driver = uc.Chrome()
    driver.get(url=category)
    time.sleep(10)
    name_category = (driver.find_element(By.TAG_NAME, "h1")).text
    print(name_category)
    while len(products_urls) < 10: 
        find_links = driver.find_elements(By.CLASS_NAME, 'tile-root')
        for link in find_links:
            products_urls.append((link.find_element(By.XPATH, ".//a")).get_attribute("href"))
        products_urls = list(set(products_urls))
        driver.execute_script("window.scrollBy(0, 1000)")
        time.sleep(1)
    products_data = []  # список для хранения информации с карточек товаров
    for url in products_urls:
        data = collect_product_info(driver=driver, url=url)
        products_data.append(data)
    with open(f'{name_category}.json', 'w', encoding='utf-8') as file:
        json.dump(products_data, file, indent=4, ensure_ascii=False)
    driver.quit()


def collect_product_info(driver, url=''):
    driver.switch_to.new_window('tab')
    tm.sleep(3)
    driver.get(url=url)
    tm.sleep(10)
    product_id = driver.find_element(
        By.XPATH, '//div[contains(text(), "Артикул: ")]'    # артикул товара
    ).text.split('Артикул: ')[1]
    page_source = driver.page_source    
    soup = BeautifulSoup(page_source, 'lxml')
    with open(f'html/product_{product_id}.html', 'w', encoding='utf-8') as file:
        file.write(page_source)
    product_name = soup.find('div', attrs={"data-widget": 'webProductHeading'}).find(     # название товара
        'h1').text.strip().replace('\t', '').replace('\n', ' ')
    product_name = (product_name).strip()
    price = (soup.find('span', {'class': 'ly7_29 l7y_29 zl0_29'})).text  
    product_data = (
        {
            'product_id': product_id,
            'product_name': product_name,
            'price': price
        }
    )
    tm.sleep(3)
    driver.close()
    driver.switch_to.window(driver.window_handles[0])
    return product_data


def main():
    for category in categories:
        get_products_links(category)


if __name__ == '__main__':
    main()


Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: