有人知道如何使用 selenium webdriver 识别 shadow dom web 元素吗?

Posted

技术标签:

【中文标题】有人知道如何使用 selenium webdriver 识别 shadow dom web 元素吗?【英文标题】:Does anybody know how to identify shadow dom web elements using selenium webdriver? 【发布时间】:2016-07-08 14:09:41 【问题描述】:

我们正在使用 selenium web 驱动程序和 python 进行测试自动化,并尝试使用 shadow dom 设计自动化 html5 应用程序。无法识别 shadow-root 下的任何元素。例如。如果我想访问下面给出的影子根下的任何元素,那么我该怎么做?任何帮助表示赞赏。

【问题讨论】:

***.com/q/36139212/954442, ***.com/questions/28911799/… 【参考方案1】:

您可以注入执行此操作的这段 javascript,然后在该元素上运行 find_element 方法:

shadow_section = mydriver.execute_script('''return document.querySelector("neon-animatable").shadowRoot''')
shadow_section.find_element_by_css(".flex")

由于你经常使用,你可能会创建一个函数,那么上面就变成了:

def select_shadow_element_by_css_selector(selector):
  running_script = 'return document.querySelector("%s").shadowRoot' % selector
  element = driver.execute_script(running_script)
  return element

shadow_section = select_shadow_element_by_css_selector("neon-animatable")
shadow_section.find_element_by_css(".flex")

您可以在结果元素上放置任何方法:

find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector

要查找多个元素(这些方法将返回一个列表):

find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector

稍后编辑:

很多时候根元素是嵌套的,第二个嵌套元素在文档中不再可用,但在当前访问的影子根中可用。我认为最好使用 selenium 选择器并注入脚本只是为了获取影子根:

def expand_shadow_element(element):
  shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
  return shadow_root

#the above becomes 
shadow_section = expand_shadow_element(find_element_by_tag_name("neon-animatable"))
shadow_section.find_element_by_css(".flex")

为了说明这一点,我刚刚在 Chrome 的下载页面中添加了一个可测试的示例,单击搜索按钮需要打开 3 个嵌套的阴影根元素:

import selenium
from selenium import webdriver
driver = webdriver.Chrome()


def expand_shadow_element(element):
  shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
  return shadow_root

selenium.__file__
driver.get("chrome://downloads")
root1 = driver.find_element_by_tag_name('downloads-manager')
shadow_root1 = expand_shadow_element(root1)

root2 = shadow_root1.find_element_by_css_selector('downloads-toolbar')
shadow_root2 = expand_shadow_element(root2)

root3 = shadow_root2.find_element_by_css_selector('cr-search-field')
shadow_root3 = expand_shadow_element(root3)

search_button = shadow_root3.find_element_by_css_selector("#search-button")
search_button.click()

【讨论】:

你碰巧知道geckodriver中的这个等价物吗?您的示例在那里不起作用 @vnportnoy 你能发布你遇到的错误吗?如果您尝试在浏览器控制台中扩展 shadowDOM,可能是浏览器问题,如下所示:document.querySelector("neon-animatable").shadowRoot 使用 geckodriver v24 在 firefox v70 上运行时会出现“循环对象值”错误。绝对是浏览器问题,但我需要使用那个特定的问题,因为我的所有其他爬虫都在那个设置中。 在我看来,您有一个单独的问题,可能需要一个全新的问题

以上是关于有人知道如何使用 selenium webdriver 识别 shadow dom web 元素吗?的主要内容,如果未能解决你的问题,请参考以下文章

数据驱动框架 - Selenium Webdriver

使用Selenium Webdriver的Silverlight和Flex应用程序自动化

如何使用Selenium WebDriver处理Windows文件上传?

如何使用 Selenium WebDriver 处理 Windows 文件上传?

JavascriptExecutor 如何在 selenium webdriver 中工作

如果站点使用 Ajax,如何检查 Selenium WebDriver?