Результат парсинга в Python список обрезается до 12 строк из 24

У меня есть готовый код парсера. Удалось спарсить нужный диапазон страниц с товаром в интернет-магазине и записать данные в CSV файл. Решил спарсить сайт конкурентов. Используя имеющийся код, стал подставлять нужные данные, запустил скрипт, но результат работы - только 50% от искомой информации на странице. Т.е. если на странице 24 товара, то парсер сохраняет только 12 товаров. Хотя видно, что парсер понял, что есть еще строки, но текст он не выдергивает. Допускаю, что это проблема с версткой сайта. Сделал урезанную версию парсера, просто в надежде выдрать все 24 строки на странице, пусть даже с бесполезными данными, но все равно на выходе только половина данных. Причем такая ситуация на всех страницах раздела.

import requests
from bs4 import BeautifulSoup

url = 'https://www.technodom.kz/ust-kamenogorsk/catalog/smartfony-i-gadzhety/smartfony-i-telefony/smartfony?page=3'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.find_all('li', class_='category-page-list__item')
i = 0    
imax = 24

while i < imax:
    itemName = items[i].text 
    print(itemName)
    i += 1

Результат работы парсера

По совету людей, решил использовать Selenium, но все равно отбор выдает только первые 12 строк из 24. Остальные 12 словно пустые.

from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By

webdriver = "D:\chromedriver_win32\chromedriver.exe"
driver = Chrome(webdriver)

url = "https://www.technodom.kz/catalog/smartfony-i-gadzhety/smartfony-i-telefony/smartfony?page=2"
driver.get(url)
itemNum = 1
itemMax = 24
itemNum_text = str(1)

i = 0


while itemNum <= itemMax:
    itemNum_text = str(itemNum)
    xPath_adress = "//*[@id='__next']/section/main/section/div/div[2]/article/ul/li[" + itemNum_text + "]/a/div/div[2]/div[1]" 
    phone_titles = driver.find_elements(By.XPATH, xPath_adress)
   # print(xPath_adress)
    print(phone_titles)
   # print(phone_titles[0].text)
    itemNum += 1
    
driver.close()

Ответы (2 шт):

Автор решения: Виктор Калгин

Удалось собрать парсинг для сайта интернет-магазина с динамической подгрузкой слотов с товарами. По совету выше, в комментариях, решил использовать Selenium. Код получился довольно растянутым, думаю, что профи могут его существенно сократить, но мой код идет прям поэтапно и показывает шаг за шагом, что и как работает. Думаю для новичков само то. При этом использовал два варианта xPath с действующим в 2022 году синтаксисом. В сети очень много гайдов по поиску элементов, типа driver.find_elements, но они все устаревшие и в текущей версии Selenium уже не работают.

from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
import csv

# Chrome Driver
webdriver = "D:\chromedriver_win32\chromedriver.exe"    # указываем путь к веб драйверу на компьютере
driver = Chrome(webdriver)  # активируем драйвер

# Переменные
pages = 16  # количество страниц
page = 1  # номер начальной страницы
itemNum = 1  # задаем порядковый номер ячейки товара
itemMax = 1  # максимальное количество ячеек на странице
itemNum_text = str(1)   # конвертируем число ячейки в строку
fileName = 'Goods_Technodom.csv'  # имя файла, куда будем записывать все данные
Index = 0  # счетчик номера по порядку
PriceList = []  # Список для цен

    # создаем csv документ с нужными столбцами
with open(fileName, 'w', encoding='utf-8-sig', newline='') as fil:
    writer = csv.writer(fil, delimiter = ";")
    writer.writerow((
        "Индекс",
        "Наименование",
        "Стоимость"
    ))

while page <= pages:
    url = "https://www.technodom.kz/catalog/smartfony-i-gadzhety/smartfony-i-telefony/smartfony?page="  + str(page)   # делаем запрос на страницу
    driver.get(url)     # запускаем драйвер хрома 
    PriceNum = 0
    # Код для одной страницы
    while itemNum <= itemMax:
        driver.execute_script("window.scrollTo(0, 1500);")  # прокручиваем экран на заданную высоту в пикселях (второе число)
    
        count_names = len(driver.find_elements(By.XPATH, "//li[@class='category-page-list__item']"))  # делаем подсчет количества ячеек для товара на странице
        itemMax = count_names       # Заносим в переменную результат подсчета
        itemNum_text = str(itemNum)  # конвертируем число в строку

        # Код для заголовка товара
        xPath_adress = "//*[@id='__next']/section/main/section/div/div[2]/article/ul/li[" + itemNum_text + "]/a/div/div[2]/div[1]"  # заполняем адрес xPath для каждого имени товара
        phone_titles = driver.find_elements(By.XPATH, xPath_adress)  # извлекаем заголовок для товара

        # код для цены товара
        price_titles = driver.find_elements(By.XPATH, "//div[@class='ProductCardV__PricesWrapper']") # ищем весь список с ценами на товары
        PriceList = price_titles[PriceNum].text.split("₸")[0] # Извлекаем только текст из цены и удаляем все что после первого знака ₸

        # код для всей страницы 
        itemNum += 1  # поднимаем счетчик для ячейки товара
        PriceNum += 1  # поднимаем счетчик для ячейки цены товара
        Index  += 1 # поднимаем счетчик номера по порядку
        GoodName = phone_titles[0].text.replace("Смартфон", "").strip() # Извлекаем только текст для заголовка товара.
                      
        print(Index, GoodName, PriceList)  # Выводим на экран список товаров

                # записываем полученные данные в csv построчно
        with open(fileName, 'a', encoding='utf-8-sig', newline='') as fil:
            writer = csv.writer(fil, delimiter = ";")
            writer.writerow((
                Index,
                GoodName,
                PriceList
            ))
          
    page += 1
    itemNum = 1
    PriceNum = 0

driver.close()
→ Ссылка
Автор решения: Сергей Ш

'Используйте селенимум или отлавливайте запросы." Отловил запрос в браузере - Инструменты веб-разработчика - Вкладка "Сеть" - Копировать как CURL - Втавил в https://curlconverter.com/ - Копировал код на Пайтоне в IDLE

import requests

limit = 400 # по умолчанию 24
page = 1
while True:
    params = {
        'city_id': '5f5f1e3b4c8a49e692fefd70',
        'limit': limit,
        'page': page,
        'sorting': 'score',
        'price': '0',
    }

    response = requests.get('https://api.technodom.kz/katalog/api/v1/products/category/smartfony', params=params)

    for i in response.json()['payload']:
        print(i['title'])
        print(i['price'])

    if response.json()['total'] < (limit * page):
        break
    page += 1
→ Ссылка