Создаю парсер, который должен парсить страницу со скидками стима, но в результате парсинга в результате дается только 3-4 игры

Рейтинг: 1Ответов: 1Опубликовано: 05.03.2023
from bs4 import BeautifulSoup
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service

url = f'https://store.steampowered.com/specials/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/93.0.4577.82 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,"
              "application/signed-exchange;v=b3;q=0.9",
}


def get_result(url, headers):
    chrome_options = Options()
    options = webdriver.ChromeOptions()
    s = Service(executable_path='C:\Пользователи\Олег\PycharmProjects\TelegramBot\chromedriver_win32\chromedriver.exe')
    driver = webdriver.Chrome(service=s, options=options)
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    driver.get(url)
    time.sleep(10)
    html = driver.page_source
    soup = BeautifulSoup(html, "lxml")
    games = soup.find_all('div', class_='salepreviewwidgets_StoreSaleWidgetRight_1lRFu')
    for game in games:
        game_name = f'Название: {game.find("div", class_="salepreviewwidgets_StoreSaleWidgetTitle_3jI46").text}'
        discount = f'Скидка: {game.find("div", class_="salepreviewwidgets_StoreSaleDiscountBox_2fpFv").text}'
        price_original = f'Цена без скидки: {game.find("div", class_="salepreviewwidgets_StoreOriginalPrice_1EKGZ").text}'
        price_sale = f'Цена после скидки: {game.find("div", class_="salepreviewwidgets_StoreSalePriceBox_Wh0L8").text}'
        print(game_name)
        print(price_original)
        print(discount)
        print(price_sale)


def main():
    get_result(url=url, headers=headers)


if __name__ == "__main__":
    main()

Ответы

▲ -1Принят

Смотрите, если самый простой способ но костыльный, то вы можете просто время ожидания сменить примерно на 90 секунд, тогда все элементы подгрузятся и вы их вытащите:

.....
driver.get(url)
time.sleep(90)
.....

Или можно использовать нажатия на кнопки, для прокуртки всех скидок, это будет выглядить примерно так, для наглядности использую вывод только имён, но думаю остальные данные вы извлечёте самостоятельно:

from bs4 import BeautifulSoup
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
......

driver.get(url)
driver.fullscreen_window() # Используем, что бы кнопка появилась на экране
time.sleep(3)
for i in range(13):
    driver.find_element(By.XPATH, '//button[@aria-label="next"]').click()
    # driver.find_element(By.TAG_NAME, 'button').click() # Нажимаем на кнопку, так как скидок 13 сейчас, то взял такое количество, думаю можно и меньше
    time.sleep(1)
time.sleep(3)
html = driver.page_source
soup = BeautifulSoup(html, "lxml")
games_names = soup.find_all('div', class_='animated_featured_capsule_TitleArtworkCtn_3DIUb')
for name in games_names:
    try: 
        name = name.find('div', 'animated_featured_capsule_TitleCtn_dXV8z').find('a').text
        print(name)
    except AttributeError:
        pass

Результат:

Deadside
The Planet Crafter
Portal 2
No Man's Sky
GTFO
Portal
Figment
Patch Quest
V Rising
Phantom Brigade
Deep Rock Galactic
Skul: The Hero Slayer
Warhammer: Vermintide

Вот вариант поиска, как вы хотели по другому классу и кнопке "Показать больше":

from selenium import webdriver, common
.....
driver.get(url)
time.sleep(3)
try:
    for i in range(100): # Нажмите столько раз, сколько посчитаете нужным
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # Прокрутить вниз страницу
        time.sleep(1) 
        driver.find_element(By.XPATH, '//div[@class="saleitembrowser_ShowContentsContainer_3IRkb"]//button[text()="Показать больше"]').click() # Нажимаем на кнопку
except common.exceptions.NoSuchElementException: # Обработаем ошибку, когда закончатся все скидки кнопка не будет найдена
    pass
time.sleep(3)
html = driver.page_source
soup = BeautifulSoup(html, "lxml")
games_names = soup.find_all('div', class_='salepreviewwidgets_StoreSaleWidgetRight_1lRFu')
for game in games_names:
    try:
        name = game.find('div', 'salepreviewwidgets_TitleCtn_1F4bc').find('a').text
        price = game.find('div', 'salepreviewwidgets_StoreSalePriceBox_Wh0L8').text
        print(f'Название:{name} - цена:{price}')
    except AttributeError:
        pass
....

Вывод:

Название:Deadside - цена:461 руб
Название:GTFO - цена:1172 руб
Название:Deep Rock Galactic - цена:263 руб
Название:Portal 2 - цена:38,50 руб
Название:Deep Rock Galactic - цена:263 руб
Название:Hunt: Showdown - цена:539 руб
....

больше информации по использования selenium