Программа доходит максимум до 1200 игр, хотя всего их 7350, таймер пытался увеличивать, ничего не поменялось, а надо брать все 7350 игр

Рейтинг: 1Ответов: 1Опубликовано: 08.03.2023
from selenium import webdriver, common
import time
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
import json

url = f'https://store.steampowered.com/specials/'
s = Service(executable_path='C:\Пользователи\Олег\PycharmProjects\TelegramBot\chromedriver_win32\chromedriver.exe')
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(service=s, options=options)
driver.get(url)
time.sleep(3)
try:
    for i in range(650):
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(2)
        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')
all_sales_dict = {}
for game in games_names:
    try:
        name = game.find('div', 'salepreviewwidgets_TitleCtn_1F4bc').find('a').text
        price_sale = game.find('div', 'salepreviewwidgets_StoreSalePriceBox_Wh0L8').text
        price_orig = game.find('div', 'salepreviewwidgets_StoreOriginalPrice_1EKGZ').text
        sale = game.find('div', 'salepreviewwidgets_StoreSaleDiscountBox_2fpFv').text
        price = (f"Цена без скидки: {price_orig}. Скидка: {sale}. Цена со скидкой: {price_sale}")
        all_sales_dict[name] = price
    except AttributeError:
        pass
with open("all_sales.json", "w", encoding="utf-8") as file:
    json.dump(all_sales_dict, file, indent=4, ensure_ascii=False)

Ответы

▲ 2Принят

Похоже проблема сейчас в том, что страница не успевает подгружаться, я изменил код и оставил комментарии. Перенес сбор данных в функцию, которую мы будем вызывать в цикле. В функции будем ждать до загрузки кнопки или до конца таймаута в 10 секунд, а затем нажимать её, собирать данные и записывать в файл. Не забудьте импорты. Количество повторений придётся определить империческим путём, думаю 5-7 раз должно хватить. Так же добавил для удобства вывод циклов, что бы знать где сейчас находится программа и после ее завршения добавил вывод количества собранных результатов. Проверьте пожалуйста как работает, напишите по результату.

...
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
...

...
    driver.get(url)
    time.sleep(3)
    count=0
    for i in range(7): # Можно увеличить счётчик на столько повторений сколько потребуется, что бы собрать все скидки
        count+=1
        print(f'Итерация N - {count}')
        try:
            f = open("all_sales.json")
            d = json.load(f)
            print('Собрано сейчас -', len(d))
        except FileNotFoundError:
            print('Собрано сейчас - 0')
            pass
        driver = try_sales(driver)
    f = open("all_sales.json")
    d = json.load(f)
    print('Сбор данных завершен, собрано -', len(d))
    


def try_sales(driver):
    try:
        for i in range(100): # Тут тоже можно увеличить допустим до 100-200
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            wait = WebDriverWait(driver, 10) # установим таймаут ожидания в 10 секунд, ниже будем ждать до появления элемента на странице или 10 секунд 
            wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="saleitembrowser_ShowContentsContainer_3IRkb"]//button[text()="Показать больше"]')))
            driver.find_element(By.XPATH, '//div[@class="saleitembrowser_ShowContentsContainer_3IRkb"]//button[text()="Показать больше"]').click()
    except common.exceptions.NoSuchElementException:
        pass
    html = driver.page_source
    soup = BeautifulSoup(html, "lxml")
    games_names = soup.find_all('div', class_='salepreviewwidgets_StoreSaleWidgetRight_1lRFu')
    all_sales_dict = {}
    for game in games_names:
        try:
            name = game.find('div', 'salepreviewwidgets_TitleCtn_1F4bc').find('a').text
            price_sale = game.find('div', 'salepreviewwidgets_StoreSalePriceBox_Wh0L8').text
            price_orig = game.find('div', 'salepreviewwidgets_StoreOriginalPrice_1EKGZ').text
            sale = game.find('div', 'salepreviewwidgets_StoreSaleDiscountBox_2fpFv').text
            price = (f"Цена без скидки: {price_orig}. Скидка: {sale}. Цена со скидкой: {price_sale}")
            all_sales_dict[name] = price
        except AttributeError:
            pass
    with open("all_sales.json", "w", encoding="utf-8") as file:
        json.dump(all_sales_dict, file, indent=4, ensure_ascii=False)
    return driver
...