问题
I am using Selenium (Python) for automating a web page. I am trying to get text from an input field that is under #shadow-root (user-agent). Xpath I used:
driver.find_element_by_xpath("**//*/p-calendar/span/input**").text
is not returning anything. Attached the screenshot of my DOM element. Requirement: To get text from the shadow root : 01:01
回答1:
As per @hayatoito
's (creator of Shadow DOM) comment:
The original motivation of introducing a closed shadow tree is
"Never allow an access to a node in a closed shadow tree, via any APIs, from outside"
, AFAIK. Like that we can not access a node in the internal hidden shadow tree which is used in<video>
element, in Blink.
In fact, I designed a closed shadow tree in such a way. If there is a way to access a node in a closed shadow tree, it should be considered as a bug of the spec.
I think it's totally okay to have an API to allow an access in the layer of Chrome apps or extensions. However, for a normal web app, I think the current agreement is
"Never allow it"
.
If we allowed it, that means we do not need a closed shadow tree. Just having an open shadow tree is enough, I think.
Furhter @Supersharp
in his comment below his own answer within the discussion How to get element in user-agent shadow root with JavaScript? mentions:
#shadow-root (user-agent)
are browser vendors native implementation so they are not documented and will never be accessible. Only open Shadow DOM are, as per the specs
WebDriver perspective
Recently, @AutomatedTester [David Burns, Chief Bacon Officer, Mozilla Corporation] initiated a discussion on WebDriver - Testability of web components
- Requests
- Proposals
- Issue Tracker
Currently Selenium Team is open for accepting pull requests for the same.
Reference
You can find a couple of relevant detailed discussions in:
- Need help to click on the element under the shadow Root (closed) type
Outro
Here you can find a relevant discussion on How to automate shadow DOM elements using selenium?
回答2:
You can use driver.execute_script
to inject JavaScript code that returns the ShadowRoot then use find_element
to get the children element of the shadow root you are looking for.
input_shadow = driver.execute_script('''return document.querySelector("$1").shadowRoot''')
div_text = inputShadow.find_element_by_tag_name("div").text
$1 - Your element's identifier or selector
.
If you are keen to using xpath to find elements
input_shadow = driver.execute_script('''return $x(\"//*/p-calendar/span/input\")[0]''')
div_text = inputShadow.find_element_by_tag_name("div").text
来源:https://stackoverflow.com/questions/63925112/how-to-read-text-that-is-under-shadow-root-user-agent