Selenium Python操作Shadow DOM输入文本后页面不识别无法触发继续按钮求助
问题根因
你遇到的两个核心问题本质是前端框架的事件监听机制和Shadow DOM元素的交互限制导致的:
- 直接通过JS修改
input的value属性,不会触发前端框架监听的input/change/blur等输入事件,框架感知不到值的变化,自然不会触发表单校验、也不会激活下一步按钮。 - 报
element is not reachable by keyboard错误,是因为自定义组件WN-input内部的原生input大概率设置了tabindex="-1"或者被组件拦截了键盘事件,Selenium的send_keys默认会校验元素是否可被键盘访问,所以直接调用会报错。
解决方案
1. 优先用「JS赋值+手动触发事件」的方案
这个方案完全绕过send_keys的交互限制,同时能让前端框架正确感知到值的变化,是操作Shadow DOM下自定义输入组件最稳定的方案。
你可以封装一个通用的赋值函数,示例如下:
def set_shadow_input_value(driver, shadow_input_element, value): # 先赋值 driver.execute_script("arguments[0].value = arguments[1];", shadow_input_element, value) # 依次触发常用的输入事件,覆盖绝大多数前端框架的监听逻辑 driver.execute_script(""" const inputEvent = new Event('input', { bubbles: true }); const changeEvent = new Event('change', { bubbles: true }); const blurEvent = new Event('blur', { bubbles: true }); arguments[0].dispatchEvent(inputEvent); arguments[0].dispatchEvent(changeEvent); arguments[0].dispatchEvent(blurEvent); """, shadow_input_element)
调用的时候替换你原来的赋值逻辑即可,示例:
# 获取三个shadow下的input元素 shadowDOM1 = driver_local.execute_script("return document.querySelector('WN-input').shadowRoot.querySelector('input')") shadowDOM2 = driver_local.execute_script("return document.querySelectorAll('WN-input')[2].shadowRoot.querySelector('input')") shadowDOM3 = driver_local.execute_script("return document.querySelectorAll('WN-input')[1].shadowRoot.querySelector('input')") # 调用函数赋值 set_shadow_input_value(driver_local, shadowDOM1, partNum) set_shadow_input_value(driver_local, shadowDOM2, str(num2buy)) set_shadow_input_value(driver_local, shadowDOM3, "CUSTX")
2. 若需使用send_keys的特殊场景
如果一定要用send_keys输入,可以先通过JS移除input的键盘访问限制,再调用输入方法:
# 先给input设置可键盘访问的属性 driver_local.execute_script("arguments[0].setAttribute('tabindex', '0'); arguments[0].removeAttribute('readonly'); arguments[0].removeAttribute('disabled');", shadow_input_element) # 再调用send_keys shadow_input_element.send_keys("你要输入的内容")
3. 关于之前触发清空值的问题
你之前通过其他输入框触发校验导致Shadow DOM输入值被清空,是因为那个操作触发了自定义组件的重渲染,组件内部的状态和你直接修改的DOM value不一致,所以重渲染后会把内部状态的空值覆盖掉DOM上的值。用上面的「赋值+触发事件」方案会同步更新组件内部的状态,不会出现值被清空的问题,不需要再额外用其他输入框触发校验。
内容的提问来源于stack exchange,提问作者FCE
相关产品推荐
相关产品推荐

