You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shadow Root中点击按钮?Selenium报错解决方案

解决Selenium点击Shadow Root内按钮的InvalidArgumentException错误

问题场景

尝试用Selenium点击网页Shadow Root中的同意广告按钮,代码如下:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
import time


print(f"Checking Browser driver...")
options = Options()
# options.add_argument('--headless=new')  
options.add_argument("start-maximized")
options.add_argument('--log-level=3')  
options.add_experimental_option("prefs", {"profile.default_content_setting_values.notifications": 1})    
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option('useAutomationExtension', False)
options.add_argument('--disable-blink-features=AutomationControlled') 
srv=Service()
driver = webdriver.Chrome (service=srv, options=options)    
waitWD = WebDriverWait (driver, 10)         

link = "https://www.firmy.cz/kraj-liberecky/liberec/1818-liberec?q="
driver.get (link)     
time.sleep(5)
shadowHost = driver.find_element(By.XPATH,'//div[@class="szn-cmp-dialog-container"]')
shadowRoot = shadowHost.shadow_root
time.sleep(5)
shadowRoot.find_element(By.XPATH, '//button[@data-testid="cw-button-agree-with-ads"]').click()      
input("Press!")

运行后抛出错误:

(selenium) C:\DEVNEU\Fiverr2025\TRY\readingmadness>python test.py
Checking Browser driver...
Traceback (most recent call last):
  File "C:\DEVNEU\Fiverr2025\TRY\readingmadness\test.py", line 29, in <module>
    shadowRoot.find_element(By.XPATH, '//button[@data-testid="cw-button-agree-with-ads"]').click()
    ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\DEVNEU\.venv\selenium\Lib\site-packages\selenium\webdriver\remote\shadowroot.py", line 53, in find_element
    return self._execute(Command.FIND_ELEMENT_FROM_SHADOW_ROOT, {"using": by, "value": value})["value"]
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\DEVNEU\.venv\selenium\Lib\site-packages\selenium\webdriver\remote\shadowroot.py", line 82, in _execute
    return self.session.execute(command, params)
           ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "C:\DEVNEU\.venv\selenium\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 384, in execute
    self.error_handler.check_response(response)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "C:\DEVNEU\.venv\selenium\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 232, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator
  (Session info: chrome=133.0.6943.60)
Stacktrace:
        GetHandleVerifier [0x00007FF64EE46F15+28773]
        (No symbol) [0x00007FF64EDB2600]
        (No symbol) [0x00007FF64EC48FAA]
        (No symbol) [0x00007FF64EC9F05A]
        (No symbol) [0x00007FF64EC9F4FC]
        (No symbol) [0x00007FF64EC91CAC]
        (No symbol) [0x00007FF64ECC728F]
        (No symbol) [0x00007FF64EC91B36]
        (No symbol) [0x00007FF64ECC7460]
        (No symbol) [0x00007FF64ECEF6F3]
        (No symbol) [0x00007FF64ECC7023]
        (No symbol) [0x00007FF64EC8FF5E]
        (No symbol) [0x00007FF64EC911E3]
        GetHandleVerifier [0x00007FF64F19425D+3490733]
        GetHandleVerifier [0x00007FF64F1ABA43+3586963]
        GetHandleVerifier [0x00007FF64F1A147D+3544525]
        GetHandleVerifier [0x00007FF64EF0C9DA+838442]
        (No symbol) [0x00007FF64EDBD04F]
        (No symbol) [0x00007FF64EDB9614]
        (No symbol) [0x00007FF64EDB97B6]
        (No symbol) [0x00007FF64EDA8CE9]
        BaseThreadInitThunk [0x00007FFC4B4D259D+29]
    RtlUserThreadStart [0x00007FFC4C7AAF38+40]

错误原因

Selenium的ShadowRoot对象对XPath定位的支持存在兼容性限制,直接使用XPath会触发InvalidArgumentException。此外,硬编码的time.sleep可靠性差,容易因页面加载速度波动导致元素未找到。

修正方案

方案1:使用CSS选择器定位(推荐)

将Shadow Root内的元素定位方式改为CSS选择器,同时用显式等待替代time.sleep,确保元素加载完成后再操作:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By


print(f"Checking Browser driver...")
options = Options()
# options.add_argument('--headless=new')  
options.add_argument("start-maximized")
options.add_argument('--log-level=3')  
options.add_experimental_option("prefs", {"profile.default_content_setting_values.notifications": 1})    
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option('useAutomationExtension', False)
options.add_argument('--disable-blink-features=AutomationControlled') 
srv=Service()
driver = webdriver.Chrome(service=srv, options=options)    
waitWD = WebDriverWait(driver, 10)         

link = "https://www.firmy.cz/kraj-liberecky/liberec/1818-liberec?q="
driver.get(link)     

# 显式等待Shadow Host加载完成
shadowHost = waitWD.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.szn-cmp-dialog-container')))
shadowRoot = shadowHost.shadow_root

# 显式等待Shadow Root内的按钮加载完成,并用CSS选择器定位
agree_button = waitWD.until(lambda d: shadowRoot.find_element(By.CSS_SELECTOR, 'button[data-testid="cw-button-agree-with-ads"]'))
agree_button.click()      

input("Press!")
driver.quit()

方案2:通过JavaScript执行点击

如果CSS选择器仍存在问题,可以直接用JavaScript穿透Shadow Root定位元素并点击,这种方式不受Selenium Shadow Root API限制:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By


print(f"Checking Browser driver...")
options = Options()
# options.add_argument('--headless=new')  
options.add_argument("start-maximized")
options.add_argument('--log-level=3')  
options.add_experimental_option("prefs", {"profile.default_content_setting_values.notifications": 1})    
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option('useAutomationExtension', False)
options.add_argument('--disable-blink-features=AutomationControlled') 
srv=Service()
driver = webdriver.Chrome(service=srv, options=options)    
waitWD = WebDriverWait(driver, 10)         

link = "https://www.firmy.cz/kraj-liberecky/liberec/1818-liberec?q="
driver.get(link)     

# 等待Shadow Host出现后,用JavaScript找到按钮并点击
waitWD.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.szn-cmp-dialog-container')))
driver.execute_script("""
    const shadowHost = document.querySelector('div.szn-cmp-dialog-container');
    const shadowRoot = shadowHost.shadowRoot;
    const agreeBtn = shadowRoot.querySelector('button[data-testid="cw-button-agree-with-ads"]');
    if (agreeBtn) agreeBtn.click();
""")

input("Press!")
driver.quit()

关键说明

  • 替换time.sleep为显式等待:避免因页面加载延迟导致的元素未找到问题,提升代码稳定性。
  • 优先使用CSS选择器:Selenium对Shadow Root内的CSS选择器支持更稳定,XPath容易触发定位错误。
  • JavaScript执行兜底:当Shadow DOM结构复杂时,直接用JS操作是最可靠的方式,无需依赖Selenium的Shadow Root API。

内容的提问来源于stack exchange,提问作者Rapid1898

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:57:33