为什么定位阴影dom元素在第5个元素处失败? [英] Why does targeting shadow dom elements fail at the 5th element?

查看:94
本文介绍了为什么定位阴影dom元素在第5个元素处失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近在这里询问如何在chrome设置中定位元素:

Recently asked how to target elements in chrome settings here: How to edit chromes search and homepage with selenium/python?

有人告诉我应该使用'shadow dom'元素,所以我继续思考如何做到这一点.

I was told I should use 'shadow dom' elements, so I went ahead and figured out how to do that.

我能够使用影子dom起始成功地在chrome的下载页面上定位搜索字段,但是当应用几乎相同的逻辑/代码来定位chrome://settings/上的特定页面或页面集时,python返回错误

I was able to successfully target the search field on chrome's download page using shadow dom inception, but when applying almost identical logic/code to target the to open a specific page or set of pages on chrome://settings/ , python returned an error

没有这样的元素:无法找到元素:{"method":"css 选择器",选择器":启动页面设置"}

no such element: Unable to locate element: {"method":"css selector","selector":"settings-on-startup-page"}

我该如何解决问题?

爱德华·弗洛里内斯库(Eduard Florinescu)评论道:当您通常还拥有动态内容以及三个以上的阴影元素时,就不可能实现自动化. 此处:如何处理硒中Shadow DOM中的元素

Eduard Florinescu commented: "when you usually have also dynamic content and more than 3 shadow elements one into another it makes impossible automation." here: How to handle elements inside Shadow DOM from Selenium

我希望有人可以在这里解释限制或解决方法吗?

I'm hoping someone can explain the limitation or workaround here?

这里是示例代码,可用于在Chromes下载页面上定位搜索字段

HERE IS EXAMPLE CODE THAT WORKS FOR TARGETING THE SEARCH FIELD ON CHROMES DOWNLOAD PAGE

import selenium
from selenium import webdriver
driver = webdriver.Chrome("C:/Users/John/Desktop/Documents/selenium/webdrivers/chromedriver.exe")

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


#start doing inception
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_tag_name('downloads-toolbar')
shadow_root2 = expand_shadow_element(root2)

root3 = shadow_root2.find_element_by_tag_name('cr-toolbar')
shadow_root3 = expand_shadow_element(root3)

root4 = shadow_root3.find_element_by_css_selector("cr-toolbar-search-field")
shadow_root4 = expand_shadow_element(root4)

root5 = shadow_root4.find_element_by_id("searchInput")

root5.send_keys('test')

这里是示例代码,不适用于打开特定页面或一组页面无线电按钮.

HERE IS EXAMPLE CODE THAT DOE NOT WORK FOR TARGETING THE OPEN A SPECIFIC PAGE OR SET OF PAGES RADIO BUTTON.

from selenium import webdriver
driver = webdriver.Chrome("C:/Users/John/Desktop/Documents/selenium/webdrivers/chromedriver.exe")


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


#start doing inception
driver.get("chrome://settings/")
root1 = driver.find_element_by_tag_name('settings-ui')
shadow_root1 = expand_shadow_element(root1)

root2 = shadow_root1.find_element_by_tag_name('settings-main')
shadow_root2 = expand_shadow_element(root2)

root3 = shadow_root2.find_element_by_tag_name('settings-basic-page')
shadow_root3 = expand_shadow_element(root3)

root4 = shadow_root3.find_element_by_css_selector("settings-section")
shadow_root4 = expand_shadow_element(root4)

root5 = shadow_root4.find_element_by_css_selector("settings-on-startup-page")
shadow_root5 = expand_shadow_element(root5)

root6 = shadow_root5.find_element_by_css_selector("settings-radio-group")
shadow_root6 = expand_shadow_element(root6)

root7 = shadow_root6.find_element_by_name("4")

root7.click()

如您所见,两个代码片段在语法和结构上几乎都是相同的,但是第二个却不起作用.

AS YOU CAN SEE, BOTH CODE SNIPPETS ARE ALMOST IDENTICAL IN SYNTAX AND STRUCTURE, YET THE SECOND DOESN'T WORK.

C:\Users\John\Desktop\Documents\selenium\projects\startpage_domain_test\venv\Scripts\python.exe C:/Users/John/Desktop/Documents/selenium/projects/startpage_domain_test/startpage_domain_test.py
Traceback (most recent call last):
  File "C:/Users/John/Desktop/Documents/selenium/projects/startpage_domain_test/startpage_domain_test.py", line 26, in <module>
    root5 = shadow_root4.find_element_by_css_selector("settings-on-startup-page")
  File "C:\Python37-32\lib\site-packages\selenium\webdriver\remote\webelement.py", line 430, in find_element_by_css_selector
    return self.find_element(by=By.CSS_SELECTOR, value=css_selector)
  File "C:\Python37-32\lib\site-packages\selenium\webdriver\remote\webelement.py", line 659, in find_element
    {"using": by, "value": value})['value']
  File "C:\Python37-32\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "C:\Python37-32\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\Python37-32\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"settings-on-startup-page"}
  (Session info: chrome=75.0.3770.142)


Process finished with exit code 1

推荐答案

看起来您只需要用shadowRoot s递归遍历元素即可.

It looks like you just have to recursively traverse the elements with shadowRoots.

尝试这样:

def find_in_shadow_dom(css):
  return driver.execute_async_script("""
    const traverse = e => {
      let el
      if(el = e.querySelector('""" + css + """')){
        arguments[0](el)
      }
      [...e.querySelectorAll('*')].filter(e => e.shadowRoot).map(e => traverse(e.shadowRoot))
    }
    [...document.querySelectorAll('*')].filter(e => e.shadowRoot).map(e => traverse(e.shadowRoot))
    arguments[0](null)
  """)

input = find_in_shadow_dom('#searchInput')
input.send_keys('testing')

设置页面的说明.

control = find_in_shadow_dom('[label="Open a specific page or set of pages"]')
# don't forget to scroll into view
driver.execute_script("arguments[0].scrollIntoView(true)", control)
control.click()

这篇关于为什么定位阴影dom元素在第5个元素处失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆