英文:
Problem with accessing Shadow DOM Tree with Python Selenium
问题
I am trying to access a deeply nested Shadow DOM on the page: https://express.adobe.com/tools/remove-background
Within one of the shadow DOMs is the element I need to access (the file input element).
I am currently trying this:
sptheme = driver.find_element(By.TAG_NAME, "sp-theme")
container = sptheme.find_element(By.ID, "quick-task-container")
shadow_root = container.find_element(By.TAG_NAME, "cclqt-remove-background").shadow_root
sptheme2 = shadow_root.find_element(By.TAG_NAME, "sp-theme")
I get this error due to the 4th line above:
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator
Element Hierarchy (I believe) to the element I wish to access:
-tag sp-theme
-id quick-task-container
-tag cclqt-remove-background
-SHADOW DOM
-tag sp-theme
-tag cclqt-workspace
-tag cclqt-image-upload
-SHADOW DOM
-class cclqt-file-upload__container
-this should be where the element is, with the ID: 'file-input'
英文:
I am trying to access a deeply nested Shadow DOM on the page: https://express.adobe.com/tools/remove-background
Within one of the shadow DOMs is the element I need to access (the file input element).
I am currently trying this:
sptheme = driver.find_element(By.TAG_NAME, "sp-theme")
container = sptheme.find_element(By.ID, "quick-task-container")
shadow_root = container.find_element(By.TAG_NAME, "cclqt-remove-background").shadow_root
sptheme2 = shadow_root.find_element(By.TAG_NAME, "sp-theme")
I get this error due to the 4th line above:
selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator
Element Hierarchy (I believe) to the element I wish to access:
-tag sp-theme
-id quick-task-container
-tag cclqt-remove-background
-SHADOW DOM
-tag sp-theme
-tag cclqt-workspace
-tag cclqt-image-upload
-SHADOW DOM
-class cclqt-file-upload__container
-this should be where the element is, with the ID: 'file-input'
答案1
得分: 1
访问 Shadow DOM 时有 两个 主要原则:
- 找到影子根元素
- 使用影子根作为与其中的元素进行交互的驱动程序。
第一种方法
> 请注意 - 自 Selenium v4.5 起,唯一支持的定位器是 CSS 选择器
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 等待影子根包装元素出现
shadow_root_wrapper = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#quick-task-container > cclqt-remove-background"))
)
# 获取影子根
shadow_root = shadow_root_wrapper.shadow_root
# 等待影子根内的图像上传区域元素可见
image_upload_area = WebDriverWait(shadow_root, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload"))
)
# 获取内部影子根
inner_shadow_root = image_upload_area.shadow_root
# 向输入字段发送图像
inner_shadow_root.find_element(By.CSS_SELECTOR, "#file-input").send_keys("path_to_image\\file.png")
第二种方法
另一种方法是利用 execute_script()
方法执行 JavaScript 代码与 Shadow DOM 进行交互:
# 为了顺利执行,您应该等待元素
shadow_root_script = "return document.querySelector('#quick-task-container > cclqt-remove-background').shadowRoot"
shadow_root = driver.execute_script(shadow_root_script)
image_upload_area = shadow_root.find_element(By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload")
inner_shadow_root = image_upload_area.shadow_root
inner_shadow_root.find_element(By.CSS_SELECTOR, "#file-input").send_keys("path_to_image\\file.png")
当处理包含许多嵌套 Shadow DOM 的复杂 DOM 时,找到元素路径的最佳方法是使用开发工具:右键单击元素 > 复制 > 复制 js 路径
(Chrome 示例)。
英文:
When accessing Shadow DOM there are two main principles:
- Find the shadow root element
- Using the shadow root as a driver to interact with elements inside
it.
First Method
> Please note - Since Selenium v4.5 the only supported locator is
> CSS-Selector
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Wait for the shadow root wrapper element to be present
shadow_root_wrapper = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#quick-task-container > cclqt-remove-background"))
)
# Get the shadow root
shadow_root = shadow_root_wrapper.shadow_root
# Wait for the image upload area element to be visible within the shadow root
image_upload_area = WebDriverWait(shadow_root, 10).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload"))
)
# Get the inner shadow root
inner_shadow_root = image_upload_area.shadow_root
# Send an image to the input field
inner_shadow_root.find_element(By.CSS_SELECTOR, "#file-input").send_keys("path_to_image\\file.png")
Second Method
Another approach is to utilize the execute_script()
method to execute JavaScript code to interact with the Shadow DOM:
# You should wait for element for smooth execution
shadow_root_script = "return document.querySelector('#quick-task-container > cclqt-remove-background').shadowRoot"
shadow_root = driver.execute_script(shadow_root_script)
image_upload_area = shadow_root.find_element(By.CSS_SELECTOR,"sp-theme > cclqt-workspace > cclqt-image-upload")
inner_shadow_root = image_upload_area.shadow_root
inner_shadow_root.find_element(By.CSS_SELECTOR, "#file-input").send_keys("path_to_image\\file.png")
When handling a complex DOM which envolved many nested Shadow DOMs the best way to find your element path is using the devtools: right click on the element > Copy > Copy js path
(example for Chrome)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论