访问Shadow DOM树在Python Selenium中存在问题。

huangapple go评论68阅读模式
英文:

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 时有 两个 主要原则:

  1. 找到影子根元素
  2. 使用影子根作为与其中的元素进行交互的驱动程序。

第一种方法

> 请注意 - 自 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:

  1. Find the shadow root element
  2. 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)

huangapple
  • 本文由 发表于 2023年5月25日 01:27:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76326041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定