06-定位一组元素find_elements

        前面的几篇都是讲如何定位一个元素,有时候一个页面上有多个对象需要操作,如果一个个去定位的话,比较繁琐,这时候就可以定位一组对象。

        webdriver 提供了定位一组元素的方法,跟前面八种定位方式一样,只是前面是单数,这里是复数形式:find_elements。

一、定位元素

1)查看百度搜索框页面元素

2)可以使用xpath进行定位。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")

eles = driver.find_elements('xpath', '//*[@id="s-top-left"]/a')

二、确认定位结果

        前面的定位策略只是一种猜想,并不一定真正获取到自己想要的对象,也许会定位到一些不想要的对象。于是可以获取对象的属性,来验证是否定位准确。这里可以获取href属性,打印出url地址。

for i in eles:
    print(i.get_attribute('href'))

三、随机函数

        搜索结果有8条,从这8条中随机取一个url。

import random

idx = random.randint(0, 7)
print(idx)

四、随机打开url

        根据生成的随机数选取一个url地址,通过driver.get(url)方式打开。

from selenium import webdriver
import random

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")

eles = driver.find_elements('xpath', '//*[@id="s-top-left"]/a')
idx = random.randint(0, 9)
driver.get(eles[idx].get_attribute("href"))

driver.quit()
<think> 我们正在讨论Selenium中的元素定位问题。用户的问题是:为什么`visibility_of_all_elements_located`方法抓不到页面元素,而`find_elements`却可以?我们需要分析这两种方法的不同行为。 首先,我们回顾一下这两个方法: 1. `find_elements`:这是WebDriver的一个方法,用于查找所有符合条件的元素,无论这些元素是否可见(即无论是否在页面上显示,只要存在于DOM中)。它立即返回找到的元素列表(可能为空)。 2. `visibility_of_all_elements_located`:这是一个“预期条件”(Expected Condition),通常与`WebDriverWait`一起使用,用于等待一组元素都可见(visible)。它要求元素不仅存在于DOM中,而且必须是可见的(即宽度和高度都大于0,并且没有被隐藏)。 因此,可能的原因有: - 元素存在但不可见:例如,元素设置了`display: none`、`visibility: hidden`、`opacity:0`,或者被其他元素覆盖等。这种情况下,`visibility_of_all_elements_located`会等待直到元素可见(如果在超时时间内变得可见则返回这些元素,否则超时异常),而`find_elements`只是查找DOM中的元素,不管可见性,所以可以找到。 - 等待时间不足:`visibility_of_all_elements_located`通常与显式等待一起使用,如果设置的等待时间不足,而元素在DOM中存在但尚未变得可见,那么该方法就会超时。而`find_elements`是立即查找,只要元素在DOM中就能找到。 - 元素在等待期间从未变得可见:如果页面状态导致元素一直不可见,那么`visibility_of_all_elements_located`就会失败,而`find_elements`仍然可以找到元素(因为这些元素确实在DOM中)。 另外,需要注意的是,`visibility_of_all_elements_located`返回的是元素列表(当所有元素都可见时),而`find_elements`也是返回元素列表,但两者对元素可见性的要求不同。 举例说明: 假设我们有一个页面,其中包含一组最初隐藏的元素(例如,通过CSS设置`display:none`)。当页面加载完成后,这些元素在DOM中,但不可见。 - 使用`find_elements`可以立即找到这些元素(因为它们存在于DOM中)。 - 使用`WebDriverWait(driver, timeout).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ...)))`则会等待,直到这些元素变得可见(比如通过某个JavaScript事件触发显示)。如果在设定的超时时间内这些元素没有变得可见,就会抛出`TimeoutException`。 因此,如果用户遇到`visibility_of_all_elements_located`找不到元素而`find_elements`可以,那么很可能是因为元素在DOM中但当前不可见,或者等待时间不够长导致元素在等待期间没有变得可见。 结论:两种方法的主要区别在于对元素可见性的要求以及是否等待。如果元素已经存在于DOM中但不可见,那么`find_elements`可以找到它们,而`visibility_of_all_elements_located`必须等到它们可见才能找到。 建议:如果用户需要操作可见的元素(例如点击、获取文本等),那么应该确保元素是可见的。因此,使用显式等待等待元素可见是一个好习惯。如果用户只是需要检查元素是否存在(而不在乎是否可见),那么可以使用`presence_of_all_elements_located`(等待元素存在于DOM中)或者直接使用`find_elements`(如果不需要等待)。 现在,我们根据用户的问题,整理回答: </think> 在Selenium自动化测试中,`visibility_of_all_elements_located`方法无法抓取元素而`find_elements`可以成功,主要源于两者对元素状态的判定标准差异。以下是具体原因分析: --- ### 核心区别 | **方法** | **判定条件** | **返回值** | |-----------------------------------|----------------------------------------------------------------------------|-----------------| | **`find_elements`** | 仅检查元素是否存在于DOM树中(无论是否可见) | 元素对象列表(可为空) | | **`visibility_of_all_elements_located`** | 要求元素:<br>1. 存在于DOM树中<br>2. **可见**(非隐藏、宽高>0、无`display:none`等) | 可见元素对象列表 | --- ### 主要原因分析 1. **元素不可见但存在于DOM**(最常见场景) -元素被CSS设置为`display: none`、`visibility: hidden`或被父元素遮挡时 - **示例**: ```html <div id="hidden-element" style="display:none">...</div> <!-- find_elements定位 --> ``` 2. **渲染延迟未达可见状态** - 异步加载内容已注入DOM但尚未完成渲染(如字体加载、动画过渡) - `visibility_of_all_elements_located`会因渲染未完成而判定失败 3. **尺寸为0的隐藏元素** - 元素宽高为0(例如`width: 0; height: 0`) - 存在于DOM但被判定为不可见[^1] 4. **预期条件的等待超时** - `visibility_of_all_elements_located`需配合`WebDriverWait`使用: ```python WebDriverWait(driver, 10).until( EC.visibility_of_all_elements_located((By.CSS_SELECTOR, ".item")) ) ``` - 若超时时间内元素未变为可见,则抛出`TimeoutException` --- ### 解决方案 1. **优先检查元素可见性状态** ```python element = driver.find_element(By.ID, "target") print(element.is_displayed()) # 输出False说明元素被隐藏 ``` 2. **改用存在性检查(如需操作隐藏元素)** ```python WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.CLASS_NAME, "data-item")) # 仅检查DOM存在性 ) ``` 3. **强制等待渲染完成(谨慎使用)** ```python from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 组合使用存在性+可见性检查 elements = WebDriverWait(driver, 15).until( lambda d: d.find_elements(By.TAG_NAME, "li") # 先获取元素 if all(element.is_displayed() for element in d.find_elements(By.TAG_NAME, "li")) else False ) ``` --- ### 典型场景示例 ```html <!-- 页面代码 --> <div class="dynamic-content"> <span class="loading">Loading...</span> <!-- 初始可见 --> <ul style="display:none"> <!-- 初始隐藏 --> <li>Item 1</li> <li>Item 2</li> </ul> </div> <script> // 3秒后显示内容 setTimeout(() => { document.querySelector("ul").style.display = "block"; }, 3000); </script> ``` - **`find_elements`**:立即返回所有`<li>`(DOM存在但隐藏) - **`visibility_of_all_elements_located`**:3秒后返回`<li>`列表(等待变为可见) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值