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

如何用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>
解决方案

问题原因解析

  1. 你定位的#fields_1056_chosen > a是Chosen插件生成的模拟下拉触发按钮,原生<select>元素(id="fields_1056")被设置为display: none隐藏,所以点击这个<a>标签能触发插件的下拉展开逻辑,但它不是原生<select>,无法用Selenium的Select类操作。
  2. failure_code_box.clear()报错是因为<a>标签不是可编辑输入元素,没有clear()方法,触发INVALID ELEMENT STATE错误。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:34:51