Как получить все данные с веб-страницы, манипулируя методом ленивой загрузки?

Я написал несколько script в python, используя селен, чтобы скрестить имя и цену разных продуктов с сайта redmart. Мой скребок нажимает на ссылку, переходит на целевую страницу, анализирует данные оттуда. Тем не менее, проблема, с которой я сталкиваюсь с этим искателем, заключается в том, что у него очень мало элементов из страницы из-за метода медленной загрузки веб-страницы. Как я могу получить все данные с каждой страницы, контролирующие процесс ленивой загрузки? Я попытался использовать метод "выполнить script", но я сделал это неправильно. Вот script, с которым я пытаюсь:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://redmart.com/bakery")
wait = WebDriverWait(driver, 10)

counter = 0    
while True:

    try:
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "li.image-facets-pill")))
        driver.find_elements_by_css_selector('img.image-facets-pill-image')[counter].click()      
        counter += 1    
    except IndexError:
        break 

    # driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    for elems in wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "li.productPreview"))):
        name = elems.find_element_by_css_selector('h4[title] a').text
        price = elems.find_element_by_css_selector('span[class^="ProductPrice__"]').text
        print(name, price)

    driver.back()
driver.quit() 

Ответ 1

Я думаю, вы могли бы использовать Selenium для этого, но если скорость ваша забота, @Andersson fooobar.com/info/45147/..., ну, вы должны реплицировать API вызывает, что сайт использует вместо этого и извлекает данные из JSON - как это делает сайт.

Если вы используете Chrome Inspector, вы увидите, что сайт для каждой из тех категорий, которые находятся во внешнем while-loop (try-block в исходном коде), вызывает API, который возвращает общие категории сайта, Все эти данные можно получить так:

categories_api = 'https://api.redmart.com/v1.5.8/catalog/search?extent=0&depth=1'
r = requests.get(categories_api).json()

Для следующих вызовов API вам нужно захватить uris в отношении хлебобулочных изделий. Это можно сделать так:

bakery_item = [e for e in r['categories'] if e['title'] == 'Bakery]
children = bakery_item[0]['children']
uris = [c['uri'] for c in children]

Теперь Uris будет списком строк ( "хлебобулочные изделия", "завтрак-лакомства-212", "нарезанный хлеб-212", "обертывания-пита-индийские хлебцы", "булочки-булочки" - 212 ',' запеченные товары-десерты ',' хлебы-кустарные хлебцы-212 ',' замороженная часть-выпечка ',' long-life-bread-toast ',' specialty-212 ']), что вы будете перейдите к другому API, найденному в Chrome Inspector, и что сайт использует для загрузки контента.

Этот API имеет следующую форму (по умолчанию возвращает меньший размер страницы, но я натолкнул его на 500, чтобы быть уверенным, что вы получите все данные в одном запросе):

items_API = 'https://api.redmart.com/v1.5.8/catalog/search?pageSize=500&sort=1024&category={}'

for uri in uris:
    r = requests.get(items_API.format(uri)).json()
    products = r['products']
    for product in products:
        name = product['title']
        # testing for promo_price - if its 0.0 go with the normal price
        price = product['pricing']['promo_price']
        if price == 0.0:
            price = product['pricing']['price']
        print("Name: {}. Price: {}".format(name, price))

Изменить: если вы хотите придерживаться селена, вы можете вставить что-то вроде этого, чтобы отменить ленивую загрузку. Вопросы о прокрутке были получены несколько раз до, поэтому ваш на самом деле является дубликатом. В будущем вы должны продемонстрировать, что вы пробовали (вы сами пытаетесь выполнить часть выполнения) и показать трассировку.

check_height = driver.execute_script("return document.body.scrollHeight;") 
while True:
    browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)
    height = driver.execute_script("return document.body.scrollHeight;") 
    if height == check_height: 
        break 
     check_height = height