Selenium无法访问closed shadow-root点击Basquete按钮求助
解决Closed Shadow-Root元素定位点击问题
原因分析
你用CDP重写attachShadow的代码逻辑没问题,但执行时机错误——必须在调用driver.get()加载页面之前注入脚本,否则页面已完成加载,那些closed模式的shadow-root已经创建完毕,重写的方法无法回溯修改已存在的shadow-root。
修复方案1:提前注入脚本(推荐)
严格按照以下顺序编写代码:
- 初始化WebDriver实例
- 执行CDP命令注入重写脚本
- 再访问目标页面
代码示例:
from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() # 先注入脚本,再加载页面 driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': """ Element.prototype._attachShadow = Element.prototype.attachShadow; Element.prototype.attachShadow = function () { return this._attachShadow({ mode: "open" }); }; """ }) # 加载目标页面 driver.get('https://www.kto.com/pt/esportes/?page=live') # 等待页面元素加载(避免因未就绪导致定位失败) driver.implicitly_wait(10) # 定位并点击按钮 driver.find_element(By.XPATH, '//*[@id="sports-container"]/div//div[1]/div[2]/main/div/div/div[1]/div[1]/div/div[2]/button').click()
修复方案2:直接用JS穿透Closed Shadow-Root点击
如果方案1不生效,可直接通过JavaScript遍历DOM结构,穿透shadow-root定位并点击元素,无需修改shadow-root模式:
# 页面加载完成后执行该脚本 basquete_btn_script = """ function traverseShadowDOM(root, selector) { let target = root.querySelector(selector); if (target) return target; // 遍历所有嵌套的shadow-root const shadowRoots = Array.from(root.querySelectorAll('*')) .map(el => el.shadowRoot) .filter(Boolean); for (const shadow of shadowRoots) { target = traverseShadowDOM(shadow, selector); if (target) return target; } return null; } // 可根据按钮的文本、属性调整选择器,比如用[data-testid="xxx"] const btn = traverseShadowDOM(document, 'button:has-text("Basquete")'); if (btn) btn.click(); """ driver.execute_script(basquete_btn_script)
注:如果has-text选择器不生效,可在浏览器开发者工具中查看按钮的具体属性(如id、data-testid),替换为更精准的CSS选择器。
额外提示
- 必须添加等待机制:使用
implicitly_wait或WebDriverWait显式等待元素可点击,避免页面未完全加载导致的定位失败。 - 先在浏览器开发者工具中手动验证选择器的有效性,确保XPath/CSS选择器能精准定位目标元素。
内容的提问来源于stack exchange,提问作者Rodrigo Viaro de Siqueira
相关产品推荐
相关产品推荐

