You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium如何获取页面所有元素(含视口外元素)

问题描述

我理解调用selenium.webdriver实例的find_elements方法时,会返回DOM中所有匹配指定定位器的元素引用。但运行以下代码时,仅获取到不到30个元素,而目标页面实际存在更多元素:

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

DRIVER_PATH = '/chromedriver'


driver = webdriver.Chrome(executable_path=DRIVER_PATH)
wait = WebDriverWait(driver, 30)


URL = 'https://labs.actionnetwork.com/markets'
driver.get(URL)
PGA_button = wait.until(EC.presence_of_element_located((By.XPATH, ".//button[@class='btn btn-light' and text()='PGA']")))
driver.execute_script("arguments[0].click();", PGA_button)

logos = driver.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']")

目标元素:
目标logo元素

调试时滚动页面会得到不同的元素列表,推测这与视口有关。请问如何获取页面上的所有logos元素?是否有办法获取页面上的所有元素(即使它们在视口外)?


问题分析

页面采用了懒加载机制——只有当元素进入浏览器视口范围时,才会被动态渲染到DOM中。直接调用find_elements只能获取当前已经加载到DOM里的元素,也就是视口内(或已滚动过的区域)的元素。

解决方法

要获取所有元素,需要先触发页面滚动,让所有懒加载的元素都完成渲染,再执行元素定位。以下是两种实用方案:

方案1:循环滚动到页面底部(适配无限滚动页面)

通过重复滚动到页面底部,直到页面高度不再变化,确保所有内容都加载完成:

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

DRIVER_PATH = '/chromedriver'

driver = webdriver.Chrome(executable_path=DRIVER_PATH)
wait = WebDriverWait(driver, 30)

URL = 'https://labs.actionnetwork.com/markets'
driver.get(URL)
PGA_button = wait.until(EC.presence_of_element_located((By.XPATH, ".//button[@class='btn btn-light' and text()='PGA']")))
driver.execute_script("arguments[0].click();", PGA_button)

# 等待初始内容加载
time.sleep(2)

last_scroll_height = driver.execute_script("return document.body.scrollHeight")
while True:
    # 滚动到当前页面底部
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    # 等待懒加载内容加载完成(可根据页面速度调整时长)
    time.sleep(3)
    # 获取新的页面高度
    new_scroll_height = driver.execute_script("return document.body.scrollHeight")
    # 高度不再变化则停止滚动
    if new_scroll_height == last_scroll_height:
        break
    last_scroll_height = new_scroll_height

# 此时DOM已包含所有元素,执行定位
logos = driver.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']")
print(f"共找到 {len(logos)} 个logo元素")

方案2:滚动到最后一个目标元素(精准触发加载)

通过定位当前已加载的最后一个目标元素,滚动到它的位置,重复直到没有新元素加载:

# 点击PGA按钮后执行以下逻辑
wait.until(EC.presence_of_element_located((By.XPATH, ".//*[@class='odds-logo ml-1']")))

while True:
    current_logo_count = len(driver.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']"))
    # 获取当前最后一个logo元素
    last_logo = driver.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']")[-1]
    # 滚动到该元素位置,触发后续内容加载
    driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'end'});", last_logo)
    # 等待新元素加载,这里用显式等待替代固定休眠更稳定
    try:
        wait.until(lambda d: len(d.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']")) > current_logo_count)
    except:
        # 没有新元素加载,退出循环
        break

# 获取所有logo元素
logos = driver.find_elements(By.XPATH, ".//*[@class='odds-logo ml-1']")

补充优化建议

  • 避免使用固定的time.sleep(),改用WebDriverWait等待元素数量变化,能提升代码稳定性,适配不同加载速度的页面;
  • 部分页面的懒加载触发条件是元素距离视口一定距离,scrollIntoView()的参数可以调整(比如block: 'center')来提前触发加载。

内容的提问来源于stack exchange,提问作者HJA24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:15:39