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

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

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:

  1. sptheme = driver.find_element(By.TAG_NAME, "sp-theme")
  2. container = sptheme.find_element(By.ID, "quick-task-container")
  3. shadow_root = container.find_element(By.TAG_NAME, "cclqt-remove-background").shadow_root
  4. sptheme2 = shadow_root.find_element(By.TAG_NAME, "sp-theme")

I get this error due to the 4th line above:

  1. selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator

Element Hierarchy (I believe) to the element I wish to access:

  1. -tag sp-theme
  2. -id quick-task-container
  3. -tag cclqt-remove-background
  4. -SHADOW DOM
  5. -tag sp-theme
  6. -tag cclqt-workspace
  7. -tag cclqt-image-upload
  8. -SHADOW DOM
  9. -class cclqt-file-upload__container
  10. -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:

  1. sptheme = driver.find_element(By.TAG_NAME, "sp-theme")
  2. container = sptheme.find_element(By.ID, "quick-task-container")
  3. shadow_root = container.find_element(By.TAG_NAME, "cclqt-remove-background").shadow_root
  4. sptheme2 = shadow_root.find_element(By.TAG_NAME, "sp-theme")

I get this error due to the 4th line above:

  1. selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: invalid locator

Element Hierarchy (I believe) to the element I wish to access:

  1. -tag sp-theme
  2. -id quick-task-container
  3. -tag cclqt-remove-background
  4. -SHADOW DOM
  5. -tag sp-theme
  6. -tag cclqt-workspace
  7. -tag cclqt-image-upload
  8. -SHADOW DOM
  9. -class cclqt-file-upload__container
  10. -this should be where the element is, with the ID: 'file-input'

答案1

得分: 1

访问 Shadow DOM 时有 两个 主要原则:

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

第一种方法

> 请注意 - 自 Selenium v4.5 起,唯一支持的定位器是 CSS 选择器

  1. from selenium.webdriver.common.by import By
  2. from selenium.webdriver.support.ui import WebDriverWait
  3. from selenium.webdriver.support import expected_conditions as EC
  4. # 等待影子根包装元素出现
  5. shadow_root_wrapper = WebDriverWait(driver, 10).until(
  6. EC.presence_of_element_located((By.CSS_SELECTOR, "#quick-task-container > cclqt-remove-background"))
  7. )
  8. # 获取影子根
  9. shadow_root = shadow_root_wrapper.shadow_root
  10. # 等待影子根内的图像上传区域元素可见
  11. image_upload_area = WebDriverWait(shadow_root, 10).until(
  12. EC.visibility_of_element_located((By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload"))
  13. )
  14. # 获取内部影子根
  15. inner_shadow_root = image_upload_area.shadow_root
  16. # 向输入字段发送图像
  17. inner_shadow_root.find_element(By.CSS_SELECTOR, "#file-input").send_keys("path_to_image\\file.png")

第二种方法

另一种方法是利用 execute_script() 方法执行 JavaScript 代码与 Shadow DOM 进行交互:

  1. # 为了顺利执行,您应该等待元素
  2. shadow_root_script = "return document.querySelector('#quick-task-container > cclqt-remove-background').shadowRoot"
  3. shadow_root = driver.execute_script(shadow_root_script)
  4. image_upload_area = shadow_root.find_element(By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload")
  5. inner_shadow_root = image_upload_area.shadow_root
  6. 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

  1. from selenium.webdriver.common.by import By
  2. from selenium.webdriver.support.ui import WebDriverWait
  3. from selenium.webdriver.support import expected_conditions as EC
  4. # Wait for the shadow root wrapper element to be present
  5. shadow_root_wrapper = WebDriverWait(driver, 10).until(
  6. EC.presence_of_element_located((By.CSS_SELECTOR, "#quick-task-container > cclqt-remove-background"))
  7. )
  8. # Get the shadow root
  9. shadow_root = shadow_root_wrapper.shadow_root
  10. # Wait for the image upload area element to be visible within the shadow root
  11. image_upload_area = WebDriverWait(shadow_root, 10).until(
  12. EC.visibility_of_element_located((By.CSS_SELECTOR, "sp-theme > cclqt-workspace > cclqt-image-upload"))
  13. )
  14. # Get the inner shadow root
  15. inner_shadow_root = image_upload_area.shadow_root
  16. # Send an image to the input field
  17. 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:

  1. # You should wait for element for smooth execution
  2. shadow_root_script = "return document.querySelector('#quick-task-container > cclqt-remove-background').shadowRoot"
  3. shadow_root = driver.execute_script(shadow_root_script)
  4. image_upload_area = shadow_root.find_element(By.CSS_SELECTOR,"sp-theme > cclqt-workspace > cclqt-image-upload")
  5. inner_shadow_root = image_upload_area.shadow_root
  6. 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:

确定