如何使用Python Selenium点击shadow-root元素内部的按钮?
问题解决建议
错误原因
- 核心逻辑错误:shadow DOM是隔离的,全局
driver只能访问顶层DOM的元素,你在查找第二层及之后的shadow host时,直接调用driver.find_element是找不到嵌套在shadow root内部的元素的,传入无效的host对象到JS脚本就会触发Cyclic object value报错 - 版本兼容问题:Selenium 3.x及更早版本不支持shadow root对象的序列化,JS返回shadow root时会触发循环引用异常
修复方案
第一步:升级Selenium到4.0+版本
Selenium 4.0及以上版本已经原生支持shadow root操作,无需手动写JS获取,直接调用元素的shadow_root属性即可:
pip install --upgrade selenium
第二步:修改元素查找逻辑
每一层shadow host都需要在上一层的shadow root上下文内查找,修正后的代码如下:
from selenium.webdriver import Firefox from selenium.webdriver.common.by import By import time # 初始化驱动 driver = Firefox(executable_path='C:/Users/Alexis/AppData/Local/Programs/Python/Python39/Tools/geckodriver.exe') driver.get('https://vacunacovidsalut.cat/') # 等待页面加载完成,后续可以替换为显式等待减少不必要的等待时间 time.sleep(5) # 逐层穿透shadow DOM # 第一层:顶层DOM找vaccinapp-app,拿它的shadow root host1 = driver.find_element(By.TAG_NAME, 'vaccinapp-app') root1 = host1.shadow_root # 第二层:在root1里找vaccinapp-shell host2 = root1.find_element(By.TAG_NAME, 'vaccinapp-shell') root2 = host2.shadow_root # 第三层:在root2里找appointment-shell host3 = root2.find_element(By.TAG_NAME, 'appointment-shell') root3 = host3.shadow_root # 第四层:在root3里找appointment-onboarding host4 = root3.find_element(By.TAG_NAME, 'appointment-onboarding') root4 = host4.shadow_root # 第五层:在root4里找mwc-button,注意原代码的下划线写法可能有误,以页面实际标签名为准 host5 = root4.find_element(By.TAG_NAME, 'mwc-button') root5 = host5.shadow_root # 找到最终按钮点击 btn_pedircita = root5.find_element(By.CSS_SELECTOR, '#button') btn_pedircita.click()
额外优化建议
- 可以把
time.sleep替换为Selenium的显式等待WebDriverWait,避免网络波动导致元素还没加载完成就查找的报错 - 执行前可以打开浏览器控制台再确认下各层shadow host的标签名拼写,避免拼写错误导致查找失败
内容的提问来源于stack exchange,提问作者AlexMnrs
相关产品推荐
相关产品推荐

