如何用Python Selenium 4.1操作非Select元素的下拉框?
问题描述
我正在为工作系统开发自动化脚本,用于关闭技术人员已完成的工单。该网站采用了Shadow Dom(User-agent)代码,但我已在开发者工具中禁用该功能。我使用PyCharm开发环境,安装了Selenium 4.1版本。
我需要操作页面上名为"Failure code"的下拉框,目标是选择其中任意选项。目前我能够定位并点击该下拉元素,但不理解为何此操作能成功(因为代码未定位原生<select>元素),却无法完成下拉选项的选择或框内内容的清除操作。
代码中的sleep计时器仅用于观察脚本执行过程,无需关注。该网站包含大量脚本逻辑,且因工作原因无法提供网站访问链接。
导入代码
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.common.exceptions import TimeoutException
处理下拉框的代码
# FAILURE CODE DROPDOWN BOX # ========================== try : failure_code_boxWait = WebDriverWait(driver,5).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#fields_1056_chosen > a"))) #(我不理解这段代码为何能生效) failure_code_box = driver.find_element(By.CSS_SELECTOR, "#fields_1056_chosen > a") time.sleep(3) failure_code_box.click() #此操作在页面上成功执行 time.sleep(3) failure_code_box.clear() #执行此方法时提示"INVALID ELEMENT STATE"错误 time.sleep(5) # quit() select = Select(failure_code_box) #移除上述报错代码后,此行代码会报错:UnexpectedTagNameException(f"Select only works on <select> elements, not on {webelement.tag_name}") select.select_by_index(2) time.sleep(3) print("SOMTHING GOOD Happened!!") quit() time.sleep(.25) # print(f"Failure Code : [{failure_code}] ") failure_code_box.send_keys(failure_code, Keys.TAB) print("SUCCESS : I SEND the TAB KEY") time.sleep(5) quit() except TimeoutException: print("ERROR:Could not find the FAILURE CODE BOX ?") # 若CSS选择器不带'a'标签会触发此错误 quit()
网页源码
<div class="form-group form-group-1056 form-group-fieldtype_entity form-group-entity-41"> <label class="col-md-12 control-label" for="fields_1056"><span class="required-label">*</span>Failure Code</label> <div class="col-md-12"> <div id="fields_1056_rendered_value"><select name="fields[1056]" id="fields_1056" class="form-control chosen-select input-medium field_1056 required" style="display: none;"><option value="">Please Select</option><option value="2">DIRTUNKEMP</option><option value="3">BROKEN</option><option value="4">DAMAGED</option><option value="5">FALSEALARM</option><option value="6">LEAKING</option><option selected="" value="7">NOTWORKING</option><option value="201">Wear and Tear</option><option value="683">NA</option></select><div class="chosen-container chosen-container-single" title="" id="fields_1056_chosen" style="width: 100%;"><a class="chosen-single"> <input class="chosen-focus-input" type="text" autocomplete="off"> <span>NOTWORKING</span> <div><b></b></div> </a> <div class="chosen-drop"> <div class="chosen-search"> <input class="chosen-search-input" type="text" autocomplete="off"> </div> <ul class="chosen-results"></ul> </div></div> <label id="fields_1056-error" class="error" for="fields_1056"></label> <script> $("#fields_1056").on("change", function(e) { $("#fields_1056-error").hide(); }); </script> <script> function prepare_add_edit_button_1056() { let value = $("#fields_1056").val() if($("#fields_1056").attr("multiple")=="multiple" || $("#btn_submodal_edit_item_1056").length==0) { $("#btn_submodal_edit_item_1056").attr("data-item-id",0).hide() return false } if(value>0) { $("#btn_submodal_add_item_1056").hide() $("#btn_submodal_edit_item_1056").attr("data-item-id",value).show() } else { $("#btn_submodal_add_item_1056").show() $("#btn_submodal_edit_item_1056").attr("data-item-id",0).hide() } } $(function(){ prepare_add_edit_button_1056() $("#fields_1056").change(function (e) { prepare_add_edit_button_1056() }); }); </script> </div> </div> </div>
解决方案
问题原因解析
- 你定位的
#fields_1056_chosen > a是Chosen插件生成的模拟下拉触发按钮,原生<select>元素(id="fields_1056")被设置为display: none隐藏,所以点击这个<a>标签能触发插件的下拉展开逻辑,但它不是原生<select>,无法用Selenium的Select类操作。 failure_code_box.clear()报错是因为<a>标签不是可编辑输入元素,没有clear()方法,触发INVALID ELEMENT STATE错误。Select(failure_code_box)报错是因为Select类仅支持原生<select>标签,传入<a>标签必然触发UnexpectedTagNameException。
两种可行解决方法
方法1:直接操作原生<select>元素
虽然原生<select>被隐藏,可通过JavaScript修改显示状态后操作:
# 等待原生select元素加载完成 failure_code_select = WebDriverWait(driver, 5).until( EC.presence_of_element_located((By.ID, "fields_1056")) ) # 通过JS显示隐藏的select元素 driver.execute_script("arguments[0].style.display = 'block';", failure_code_select) # 使用Select类正常操作 select = Select(failure_code_select) select.select_by_index(2) # 选择索引为2的选项(对应"BROKEN") # 也可使用其他选择方式:select.select_by_value("3") 或 select.select_by_visible_text("BROKEN")
方法2:模拟用户操作Chosen插件
完全模拟人工操作流程:点击触发按钮→等待下拉选项→点击目标选项:
# 点击Chosen插件触发按钮展开下拉 failure_code_trigger = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "#fields_1056_chosen > a")) ) failure_code_trigger.click() # 等待下拉选项加载,选择目标选项(示例选择"BROKEN") target_option = WebDriverWait(driver, 5).until( EC.element_to_be_clickable((By.XPATH, "//div[@id='fields_1056_chosen']//ul[@class='chosen-results']//li[text()='BROKEN']")) ) target_option.click() # 也可按索引选择(li索引从1开始,第二个选项对应li:nth-child(2)) # target_option = WebDriverWait(driver, 5).until( # EC.element_to_be_clickable((By.CSS_SELECTOR, "#fields_1056_chosen .chosen-results li:nth-child(2)")) # ) # target_option.click()
内容的提问来源于stack exchange,提问作者ConleyM
相关产品推荐
相关产品推荐

