ng-select下拉框Selenium模拟箭头键报错Element not interactable
问题:Selenium操作下拉框提示Element not interactable,点击正常但send_keys失效
我尝试用以下代码遍历网站下拉框,代码中click()能正常展开下拉框,但执行state_name.send_keys(Keys.ARROW_DOWN)时命令提示符报错Element not interactable,手动用箭头键可以操作该下拉框,找不到问题根源。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import time def main(): try: # url of the website where the data will be collected from url = "https://app.cpcbccr.com/ccr/#/caaqm-dashboard-all/caaqm-landing" # path to the browser on my computer browser = webdriver.Chrome() # access the website browser.get(url) time.sleep(30) browser.find_element(By.XPATH, '/html/body/app-root/app-caaqm-dashboard/div[1]/div/main/section/app-caaqm-landing/div[2]/div[1]/div[1]/div[1]').click() time.sleep(30) browser.switch_to.window(browser.window_handles[1]) print("-------------------------------------") print(browser.current_url) print("-------------------------------------") # Locate the state_name element state_name = browser.find_element(By.XPATH, '/html/body/app-root/app-caaqm-dashboard/div[1]/div/main/section/app-caaqm-view-data/div/div/div[1]/div[1]/div/ng-select') # Check if the state_name element is inside an iframe if state_name.get_attribute("tagName").lower() == "iframe": # Switch to the iframe browser.switch_to.frame(state_name) # Locate the state_name element within the iframe state_name = browser.find_element(By.XPATH, 'your_xpath_here') # Click on the state_name element to expand the dropdown state_name.click() time.sleep(3) # Simulate keyboard interactions to loop over the options list_of_state_names = [] state_name.send_keys(Keys.ARROW_DOWN) list_of_state_names.append(state_name.get_attribute("value")) state_name_count = 0 while True: # Send an arrow down key to navigate to the next option state_name.send_keys(Keys.ARROW_DOWN) time.sleep(0.5) # Check if the selected option is the first option again, indicating we have looped through all the options if state_name.get_attribute("value") == list_of_state_names[0]: break # Get the current selected option text state_name_count += 1 list_of_state_names[state_name_count] = state_name.get_attribute("value") for state in list_of_state_names: print(state) while (True): pass except Exception as exception: print("-------------------------------------") print(exception) print("-------------------------------------") raise(exception) if __name__ == '__main__': main()
解决方案
问题原因
你定位的是ng-select容器元素,点击展开下拉后,箭头键的实际作用对象是下拉列表里的选项元素,而非容器本身,所以向容器发送键盘事件会触发不可交互报错。
修正方案
直接定位下拉展开后的选项元素,遍历操作即可,无需模拟键盘:
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 import time def main(): try: url = "https://app.cpcbccr.com/ccr/#/caaqm-dashboard-all/caaqm-landing" browser = webdriver.Chrome() browser.get(url) # 等待页面加载,替换固定sleep为显式等待更可靠 WebDriverWait(browser, 30).until( EC.element_to_be_clickable((By.XPATH, '/html/body/app-root/app-caaqm-dashboard/div[1]/div/main/section/app-caaqm-landing/div[2]/div[1]/div[1]/div[1]')) ).click() # 等待新窗口打开并切换 WebDriverWait(browser, 30).until(lambda d: len(d.window_handles) > 1) browser.switch_to.window(browser.window_handles[1]) print("-------------------------------------") print(browser.current_url) print("-------------------------------------") # 定位ng-select容器并点击展开下拉 state_select = WebDriverWait(browser, 10).until( EC.element_to_be_clickable((By.XPATH, '/html/body/app-root/app-caaqm-dashboard/div[1]/div/main/section/app-caaqm-view-data/div/div/div[1]/div[1]/div/ng-select')) ) state_select.click() # 等待下拉选项加载完成,定位所有选项 state_options = WebDriverWait(browser, 10).until( EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'ng-dropdown-panel .ng-option')) ) # 遍历选项,获取文本并打印(如需选择可添加click()) list_of_state_names = [] for option in state_options: state_text = option.text list_of_state_names.append(state_text) print(state_text) # 如果需要选中当前选项,取消注释下面一行 # option.click() # time.sleep(1) print("所有状态列表:", list_of_state_names) # 保持窗口打开,方便查看 while True: pass except Exception as exception: print("-------------------------------------") print(exception) print("-------------------------------------") raise exception if __name__ == '__main__': main()
关键优化点
- 用显式等待替换固定
time.sleep(),提升代码稳定性,避免因页面加载慢导致的元素定位失败 - 直接定位下拉选项元素,绕开键盘模拟的交互问题
- 使用CSS选择器定位选项,比绝对XPATH更健壮,不易因页面结构变化失效
内容的提问来源于stack exchange,提问作者Nguyễn Văn Chiến
相关产品推荐
相关产品推荐

