使用Python Selenium抓取Shadow Root元素时遇AttributeError问题求助
解决Selenium操作Shadow DOM时的AttributeError问题
问题背景
我在一个小型项目中尝试抓取网站数据,所需数据隐藏在HTML的#Shadow-root标签下。使用Selenium编写了如下代码:
def expand_shadow_element(element): shadow_root = driver.execute_script('return arguments[0].shadowRoot', element) return shadow_root url = "https://new.abb.com/products/SK615502-D" #Initializing the webdriver options = webdriver.ChromeOptions() driver = webdriver.Chrome(executable_path="/Users/ritchevy/Desktop/scraping-glassdoor/chromedriver", options=options) timeout = 10 wait = WebDriverWait(driver, timeout) driver.set_window_size(1120, 1000) driver.get(url) root1 = driver.find_element(By.CSS_SELECTOR,"pis-products-details-attribute-groups") shadow_root1 = expand_shadow_element(root1) shadow_container_root = shadow_root1.find_element(By.CSS_SELECTOR,"div")
执行时触发错误:
---> 35 shadow_container_root = shadow_root1.find_element(By.CSS_SELECTOR,"div") 36 AttributeError: 'dict' object has no attribute 'find_element'
问题原因
新版Selenium(尤其是v4+)通过execute_script获取shadowRoot时,返回的是字典格式的元素元数据,而非可直接调用find_element方法的WebElement对象,因此触发属性不存在的报错。
解决方案
方法1:使用Selenium原生shadow_root属性(推荐)
Selenium 4.0及以上版本已为WebElement对象内置shadow_root属性,无需通过JS脚本获取,直接调用即可得到可操作的Shadow Root对象:
def expand_shadow_element(element): return element.shadow_root # 直接返回原生Shadow Root对象 # 后续代码保持原有逻辑 root1 = driver.find_element(By.CSS_SELECTOR,"pis-products-details-attribute-groups") shadow_root1 = expand_shadow_element(root1) shadow_container_root = shadow_root1.find_element(By.CSS_SELECTOR,"div")
方法2:将字典转换为WebElement对象
如果必须保留JS脚本的方式,可以通过driver.create_web_element方法把返回的字典转换为可操作的WebElement:
def expand_shadow_element(element): shadow_root_dict = driver.execute_script('return arguments[0].shadowRoot', element) # 提取字典中的元素ID并转换为WebElement return driver.create_web_element(shadow_root_dict['element-6066-11e4-a52e-4f735466cecf']) # 调用逻辑不变 root1 = driver.find_element(By.CSS_SELECTOR,"pis-products-details-attribute-groups") shadow_root1 = expand_shadow_element(root1) shadow_container_root = shadow_root1.find_element(By.CSS_SELECTOR,"div")
额外建议
- 检查并升级Selenium版本:通过
pip show selenium查看版本,若低于4.0执行pip install --upgrade selenium - 结合显式等待提升稳定性:操作Shadow DOM内元素时,用
WebDriverWait等待元素加载完成,避免超时或未找到元素的问题:
from selenium.webdriver.support import expected_conditions as EC shadow_root1 = expand_shadow_element(root1) shadow_container_root = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div")))
内容的提问来源于stack exchange,提问作者rorivy15
相关产品推荐
相关产品推荐

