Selenium Java获取动态下拉框全量选项(解决getText空值问题)
问题背景
使用Selenium Java开展Web自动化测试时,目标站点包含2个动态下拉框,下拉选项对应的HTML节点仅在滚动到可视区域时才会生成渲染。通过xpath定位可见选项存入列表后遍历打印,列表中部分记录返回空值,需要实现获取下拉列表内的全部选项,包含未滚动到可视区域的非可见选项。
下拉框HTML结构
<div class="ant-col ant-form-item-control"> <div class="ant-form-item-control-input"> <div class="ant-form-item-control-input-content"> <div class="ant-select ant-select-lg ant-select-single ant-select-show-arrow"> <div class="ant-select-selector"> <span class="ant-select-selection-search"> <input id="company_industry" autocomplete="off" type="search" class="ant-select-selection-search-input" role="combobox" aria-haspopup="listbox" aria-owns="company_industry_list" aria-autocomplete="list" aria-controls="company_industry_list" aria-activedescendant="company_industry_list_9" readonly="" unselectable="on" value="" style="opacity: 0;" aria-expanded="false"> </span> <span class="ant-select-selection-item" title="Automotive">Automotive</span></div> <span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;"> <span role="img" aria-label="down" class="anticon anticon-down ant-select-suffix"> <svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"> <path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></span></span></div></div></div></div>
现有测试代码
companylist = portalElements.company_type_list(); for (int i = 0; i < companylist.size(); i++) { System.out.println("Total company list is :" + companylist.get(i).getText()); }
其中companylist为存储下拉选项元素的List对象,定位所有选项使用的xpath为//div[@class='ant-select-item ant-select-item-option']。
问题原因
返回空值的核心原因是该下拉框基于Ant Design虚拟滚动机制实现:未滚动到可视区域的选项不会挂载到DOM树中,直接通过xpath定位只能获取当前已渲染的少量选项;滚动过程中离开可视区的旧选项DOM会被销毁,代码中持有的元素引用失效,调用getText()就会返回空值。
可行解决方案
方案1:循环滚动收集全量选项(适配虚拟滚动场景)
核心逻辑为每次滚动到当前已渲染列表的最后一个选项,触发下一批选项渲染,直到滚动后收集到的选项总数量不再变化,去重后即可得到全量选项。
import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; import java.util.*; // 点击下拉框触发展开 WebElement selectInput = driver.findElement(By.id("company_industry")); selectInput.click(); // 等待下拉框展开完成 new WebDriverWait(driver, Duration.ofSeconds(3)) .until(d -> "true".equals(selectInput.getAttribute("aria-expanded"))); // 定位下拉虚拟滚动容器 WebElement scrollContainer = driver.findElement(By.cssSelector(".ant-select-dropdown .rc-virtual-list-holder")); Actions actions = new Actions(driver); // 用有序Set存储选项,自动去重 Set<String> allOptions = new LinkedHashSet<>(); int lastOptionSize = 0; while (true) { // 获取当前已渲染的所有选项 List<WebElement> currentRenderOptions = driver.findElements(By.xpath("//div[@class='ant-select-item ant-select-item-option']")); for (WebElement option : currentRenderOptions) { // 优先读取文本,文本为空时读取title属性兜底 String optionText = option.getText().isBlank() ? option.getAttribute("title") : option.getText(); if (!optionText.isBlank()) { allOptions.add(optionText); } } // 选项总数不再增长说明已经滚动到列表底部 if (allOptions.size() == lastOptionSize) { break; } lastOptionSize = allOptions.size(); // 移动到当前最后一个选项,触发下一批选项加载 actions.moveToElement(currentRenderOptions.get(currentRenderOptions.size() - 1)).perform(); Thread.sleep(300); // 等待DOM渲染完成,可替换为显式等待提升稳定性 } // 遍历打印全量选项 for (String optionName : allOptions) { System.out.println("Total company list is :" + optionName); }
如果下拉框支持检索输入,可尝试输入空字符或通配符触发全量选项渲染,部分版本Ant Design可直接加载全部选项,无需滚动。
方案2:拦截接口获取全量选项(稳定性最高)
绝大多数动态下拉的选项数据都来自后端接口,可通过Selenium内置的DevTools能力或者代理工具拦截下拉选项对应的接口响应,直接拿到全量选项数据,无需处理滚动、DOM渲染、元素失活等问题,稳定性远高于DOM定位方案。
内容的提问来源于stack exchange,提问作者Arpit24
相关产品推荐
相关产品推荐

