【问题标题】:How to do pagination with scroll in Selenium?如何在 Selenium 中使用滚动进行分页?
【发布时间】:2021-07-19 06:07:43
【问题描述】:

我需要为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]

【问题讨论】:

  • 我认为您的问题中缺少的关键是您如何提取数据?我认为当您向下滚动时“已看到”元素会消失,因此您无法一次加载页面上的所有内容。
  • @tomjn 是的,请问您有什么想法吗?
  • 是的,但你没有回答我的问题。你是如何提取物品的?
  • @tomjn 我更新了我的问题并回答了你的问题,谢谢
  • 谢谢,但是你能不能给我们整个parse 函数或者你叫它的任何东西,而不是小的sn-ps,这样我们就可以看到selenium 代码是如何与Selector 交互的代码?如果不是太多,整个蜘蛛会更好

标签: python selenium selenium-webdriver scroll scrapy


【解决方案1】:

正如评论的那样,如果没有看到你的整个蜘蛛,很难看出你在哪里出错了,但如果我们假设你的解析使用了 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,这是scrapy内部使用的)
  • 我们提取我们需要的信息。显示的产品都具有data-test 属性。如果这是scrapy.Spider 我会yield 信息,但在这里我只是将它添加到所有项目的字典中。
  • 在获得所有可见项后,我们尝试找到具有data-test 属性的div 的第一个后续兄弟,没有具有data-test 属性(using the css + symbol)
  • 如果不存在这样的元素(因为我们已经看到了所有项目),则退出循环,否则将该元素滚动到视图中并暂停一秒钟
  • 重复直到解析完所有项目

【讨论】:

  • 我没有使用scrapy的Request,在我的代码响应中是parsel.Selector(driver.page_source)。我运行了你的代码,我有 Number of items = 42 但在网站上有超过 300 个项目
  • @parik 正如我上面所说的,我得到 300 个运行代码的项目(每次我运行它)。你看到 Firefox 滚动到页面底部了吗?
  • 是的,你是对的,它有效,非常感谢你
【解决方案2】:

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

【讨论】:

    【解决方案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
    

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

    如果这是您要查找的内容,请将其标记为答案。

    【讨论】:

    • 这个问题是页面中间的一些元素没有加载。
    • 这就是为什么你应该使用我的解决方案:)
    • 对不起,我没有发现您的解决方案与我尝试的解决方案之间的差异,您没有错误,因为在您的情况下,您没有很多产品,如果您尝试 yith此网址您的解决方案将不起作用compraonline.bonpreuesclat.cat/products/search?q=pasta
    • 我试过你的解决方案,我只有前 30 个产品
    • 应该可以!您必须每次在循环中滚动一页高度,直到到达底部。我看到了你正在处理的页面。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2020-04-01
      • 2019-02-10
      • 2020-04-02
      • 1970-01-01
      • 2018-06-15
      • 1970-01-01
      • 2014-01-26
      • 2016-10-17
      相关资源
      最近更新 更多