如何用Selenium选择多层下拉日历菜单中的日期
解决HKEX网站日历日期选择问题
问题背景
目标网站:https://www3.hkexnews.hk/sdw/search/mutualmarket.aspx?t=hk&t=hk
日历对应的HTML元素:
<input name="txtShareholdingDate" type="text" value="2022/07/15" id="txtShareholdingDate" class="input-searchDate active" data-reset="2022/07/16" readonly="readonly">
尝试的方法及问题:
- 点击input后,无头浏览器中出现年/月/日下拉栏,但无法定位选择元素,报错
Unable to locate element - 使用
Select类处理该元素,报错:
UnexpectedTagNameException: Message: Select only works on <select> elements, not on <input>
错误原因
Select类仅适用于<select>标签,目标元素是<input>,因此无法使用。- 日历下拉选项属于动态渲染元素,点击input后才会生成,直接定位会因元素未加载完成导致找不到。
解决方案
方案1:直接通过JavaScript修改input值(最简单高效)
该input虽带有readonly属性,但可通过JavaScript绕过限制,直接设置日期值:
from selenium import webdriver browser = webdriver.Chrome(executable_path=r'D:\chromedriver.exe') browser.get("https://www3.hkexnews.hk/sdw/search/mutualmarket.aspx?t=hk&t=hk") # 用JS修改input的value属性 target_date = "2021/09/21" browser.execute_script(f'document.getElementById("txtShareholdingDate").value = "{target_date}"') # 可选:触发日期变更后的事件(若页面需要验证日期有效性) browser.execute_script('document.getElementById("txtShareholdingDate").dispatchEvent(new Event("change"))')
方案2:模拟点击日历下拉选项(适合必须模拟交互的场景)
使用显式等待确保日历元素加载完成后再操作:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC browser = webdriver.Chrome(executable_path=r'D:\chromedriver.exe') browser.get("https://www3.hkexnews.hk/sdw/search/mutualmarket.aspx?t=hk&t=hk") wait = WebDriverWait(browser, 10) # 点击日历输入框,弹出选择面板 date_input = wait.until(EC.element_to_be_clickable((By.ID, "txtShareholdingDate"))) date_input.click() # 选择年份:定位年份下拉框并点击目标年份 year_select = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".ui-datepicker-year"))) year_select.click() target_year = wait.until(EC.element_to_be_clickable((By.XPATH, f"//select[@class='ui-datepicker-year']/option[text()='2021']"))) target_year.click() # 选择月份:定位月份下拉框并点击目标月份(9月对应索引8) month_select = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".ui-datepicker-month"))) month_select.click() target_month = wait.until(EC.element_to_be_clickable((By.XPATH, f"//select[@class='ui-datepicker-month']/option[@value='8']"))) target_month.click() # 选择日期:点击目标日期 target_day = wait.until(EC.element_to_be_clickable((By.XPATH, f"//table[@class='ui-datepicker-calendar']//a[text()='21']"))) target_day.click()
说明
- 方案1无需依赖日历组件渲染,执行速度快,适配大多数场景。
- 方案2模拟真实用户交互,若页面存在日期验证逻辑,可确保触发相关校验事件。
内容的提问来源于stack exchange,提问作者newpop22
相关产品推荐
相关产品推荐

