代码之家  ›  专栏  ›  技术社区  ›  parik

如何在Selenium中使用滚动进行分页?

  •  0
  • parik  · 技术社区  · 3 年前

    我需要为 this page :

    我读过 this question 我试着这样做:

    scrolls = 10
    while True:
        scrolls -= 1
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        time.sleep(3)
        if scrolls < 0:
            break
    

    我需要向下滚动以获取所有产品,但我不知道需要滚动多少次才能获取所有产品。

    我也试着有一个大屏幕

    'SELENIUM_DRIVER_ARGUMENTS': ['--no-sandbox', '--window-size=1920,30000'],
    

    向下滚动

    time.sleep(10) 
    self.driver.execute_script("window.scrollBy(0, 30000);")
    

    有人知道如何获得所有产品吗? 如果Selenium不是最好的解决方案,我对另一种解决方案持开放态度。 谢谢。

    更新1: 我需要所有的产品ID。为了获得产品ID,我使用了以下方法:

    products = response.css('div.jfJiHa > .iepIep')
            for product in products:
                detail_link = product.css('a.jXwbaQ::attr("href")').get()
                product_id = re.findall(r'products/(\d+)', detail_link)[0]
    
    0 回复  |  直到 3 年前
        1
  •  1
  •   tomjn    3 年前

    正如所评论的那样,如果没有看到你的整个蜘蛛,很难看出你在哪里出了问题,但如果我们假设你的解析是使用 scrapy 这就是为什么你总是只收到30件产品。

    您需要从中创建一个新的选择器 driver 在每次滚动和查询之后。从页面中获取300个项目的完整代码示例是

    import re
    import time
    from pprint import pprint
    
    import parsel
    from selenium.common.exceptions import NoSuchElementException
    from selenium.webdriver import Firefox
    
    with Firefox() as driver:
        driver.get("https://www.compraonline.bonpreuesclat.cat/products/search?q=pasta")
    
        all_items = {}
    
        while True:
            sel = parsel.Selector(driver.page_source)
            for product in sel.css("div[data-test] h3 > a"):
                name = product.css("::text").get()
                product_id = re.search("(\d+)", product.attrib["href"]).group()
                all_items[product_id] = name
            try:
                element = driver.find_element_by_css_selector(
                    "div[data-test] + div.iepIep:not([data-test])"
                )
            except NoSuchElementException:
                break
            driver.execute_script("arguments[0].scrollIntoView(true);", element)
            time.sleep(1)
    
        pprint(all_items)
        print("Number of items =", len(all_items))
    

    这个的关键点

    • 使用页面后 driver.get 我们开始循环
    • 我们创造了一个新的 Selector (这里我直接使用 parsel.Selector 这是什么 内部使用)
    • 我们提取我们需要的信息。显示的产品都有 data-test 属性。如果这是一个 scrapy.Spider 我愿意 yield 信息,但在这里我只是把它添加到所有项目的词典中。
    • 在获取所有可见项后,我们试图找到 div 用一个 数据测试 属性,那 有一个 数据测试 属性 (using the css + symbol)
    • 如果不存在这样的元素(因为我们已经看到了所有项目),则跳出循环,否则将该元素滚动到视图中并暂停一秒钟
    • 重复此操作,直到解析完所有项目
        2
  •  1
  •   Prophet    3 年前

    每次阅读展示的产品时,尝试向下滚动可见屏幕高度量页面,直到 //button[@data-test='footer-feedback-button'] 或者位于底部的任何其他元素都是可见的

        3
  •  1
  •   Swaroop Humane    3 年前

    此代码可能会有所帮助-

    from selenium import webdriver
    from selenium.common.exceptions import StaleElementReferenceException
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    
    driver = webdriver.Chrome()
    wait = WebDriverWait(driver, 30)
    
    driver.get('https://www.compraonline.bonpreuesclat.cat/products/search?q=pasta')
    
    BaseDivs = driver.find_elements_by_xpath("//div[contains(@class,\"base__Wrapper\")]")
    
    for div in BaseDivs:
        try:
            wait.until(EC.visibility_of_element_located((By.XPATH, "./descendant::img")))
            driver.execute_script("return arguments[0].scrollIntoView(true);", div)
        except StaleElementReferenceException:
            continue
    

    此代码将等待图像加载,然后聚焦于元素。这样,它会自动向下滚动到页面末尾。

    如果这就是你要找的,请标记答案。

        4
  •  0
  •   parik    3 年前

    我解决了我的问题,但不是用Selenium,我们可以通过另一个请求获得所有搜索产品: https://www.compraonline.bonpreuesclat.cat/api/v4/products/search?limit=1000&offset=0&sort=favorite&term=pasta