英文:
Selenium: how to get element in shadow root of html page code?
问题
我需要使用Selenium获取按钮元素,以连接MetaMask钱包到Polygon网络桥。
我需要找到的按钮如下所示:
但是,据我了解,该按钮被隐藏在HTML页面的阴影根中。
如果我尝试通过右键单击和“检查”来查找按钮的HTML代码,我可以尝试复制它的XPath。
当我粘贴它时是:/button
这不起作用:
metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
metamask.click()
会导致错误。这些错误的文本每次都相同,因此我将在最后粘贴它。
如果我尝试右键单击,“检查”并复制CSS选择器,它也不起作用。
复制的CSS选择器是:button:nth-child(1)
我无法使用这个选择器获取按钮。
现在,当我尝试通过CSS选择器或XPath查找按钮时出现的错误文本如下所示:
Traceback (most recent call last):
File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\main.py", line 126, in <module>
metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\venv\Lib\site-packages\selenium\webdriver\support\wait.py", line 95, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
Backtrace:
GetHandleVerifier [0x00B9A813+48355]
(No symbol) [0x00B2C4B1]
(No symbol) [0x00A35358]
(No symbol) [0x00A609A5]
(No symbol) [0x00A60B3B]
(No symbol) [0x00A8E232]
(No symbol) [0x00A7A784]
(No symbol) [0x00A8C922]
(No symbol) [0x00A7A536]
(No symbol) [0x00A582DC]
(No symbol) [0x00A593DD]
GetHandleVerifier [0x00DFAABD+2539405]
GetHandleVerifier [0x00E3A78F+2800735]
GetHandleVerifier [0x00E3456C+2775612]
GetHandleVerifier [0x00C251E0+616112]
(No symbol) [0x00B35F8C]
(No symbol) [0x00B32328]
(No symbol) [0x00B3240B]
(No symbol) [0x00B24FF7]
BaseThreadInitThunk [0x76A100C9+25]
RtlGetAppContainerNamedObjectPath [0x77D77B4E+286]
RtlGetAppContainerNamedObjectPath [0x77D77B1E+238]
这是Selenium无法找到和点击元素时常见的错误。
页面HTML代码中的按钮元素(最好尝试自己在HTML代码中定位元素)
我该如何使用Selenium找到并点击此按钮?
更新:
我找到了如何定位阴影根内部元素的信息:
shadow_element = driver.execute_script("return document.querySelector('w3m-modal').shadowRoot.querySelector('div').querySelector('div')")
然而,我仍然无法创建路径到我的目标按钮。
上面的代码在正确的阴影根内到达一个div,但无法捕获在以下HTML注释之后的任何元素:
<!--?lit$702571791$-->
我该如何继续并捕获此注释之后的元素?
英文:
I need to get the element of the button to connect the MetaMask wallet to the polygon network bridge using selenium.
the button I need to find:
But the button, as I understand it is hidden in shadow root of the html page.
If I find HTML code of the button with right click and 'inspect', I can try to copy it s X-Path.
When I paste it is: /button
That does not work:
metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
metamask.click()
Results in an error. Text of these errors is every time the same so I will paste it in the end.
If I try to right click, 'inspect' and copy CSS-Selector it also does not work.
The CSS-Selector copied is: button:nth-child(1)
I can not get the button with this.
Now, text of the error which arises when I try to find the button by CSS-Selector or X-Path:
Traceback (most recent call last):
File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\main.py", line 126, in <module>
metamask = wait.until(EC.element_to_be_clickable((By.XPATH, '/button')))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\childoflogos\Desktop\selenium_airdrop_hunter\venv\Lib\site-packages\selenium\webdriver\support\wait.py", line 95, in until
raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
Backtrace:
GetHandleVerifier [0x00B9A813+48355]
(No symbol) [0x00B2C4B1]
(No symbol) [0x00A35358]
(No symbol) [0x00A609A5]
(No symbol) [0x00A60B3B]
(No symbol) [0x00A8E232]
(No symbol) [0x00A7A784]
(No symbol) [0x00A8C922]
(No symbol) [0x00A7A536]
(No symbol) [0x00A582DC]
(No symbol) [0x00A593DD]
GetHandleVerifier [0x00DFAABD+2539405]
GetHandleVerifier [0x00E3A78F+2800735]
GetHandleVerifier [0x00E3456C+2775612]
GetHandleVerifier [0x00C251E0+616112]
(No symbol) [0x00B35F8C]
(No symbol) [0x00B32328]
(No symbol) [0x00B3240B]
(No symbol) [0x00B24FF7]
BaseThreadInitThunk [0x76A100C9+25]
RtlGetAppContainerNamedObjectPath [0x77D77B4E+286]
RtlGetAppContainerNamedObjectPath [0x77D77B1E+238]
A common error when selenium is unable to find and click an element
Button element in HTML code of the page (better try to locate the element in html code yourself)
How can I find and click this button with selenium?
UPDATE:
I found information on how to locate elements inside shadow root:
shadow_element = driver.execute_script("return document.querySelector('w3m-modal').shadowRoot.querySelector('div').querySelector('div')")
Yet still I can not make a path to my target button
Code above reaches one of divs inside of correct shadow root, yet can not grasp any element after following html comment:
<!--?lit$702571791$-->
How do I proceed and grasp elements that go after the comment above?
答案1
得分: 2
你首先需要使用任何策略(XPath、CSS选择器、名称等)找到包含shadow-root
的元素。
在你的情况下,这个元素将是标签<w3m-wallet-button name="MetaMask">
导入所需的模块:
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
[更新]:
- 该网站上的各种元素都嵌套在
shadow-root
内。 - 例如,您的目标/所需按钮嵌套在一个5层嵌套的
shadow-root
内。
以下是完整的工作解决方案:
import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
options = ChromeOptions()
options.add_argument("--start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
url = "https://wallet.polygon.technology/?redirectOnConnect=zkEVM_bridge"
driver.get(url)
# 点击“连接到钱包”按钮
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.navbar__apps-section__auth__login"))).click()
time.sleep(2)
driver.execute_script("""document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();""")
time.sleep(5)
- 在点击<kbd>连接到钱包</kbd>后,我们等待1-2秒,以确保叠加窗口可见,尽管它出现得非常快。
- 用于定位并点击所需按钮的JavaScript查询
document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();
如果您想要点击第二个或第三个钱包选项,只需在上述JavaScript查询中将
querySelectorAll('w3m-wallet-button')[0]
分别替换为querySelectorAll('w3m-wallet-button')[1]
或querySelectorAll('w3m-wallet-button')[2]
。
英文:
you first need to locate the element that contains the shadow-root
using any strategy (XPath, CSS selector, name, etc).
In your case, this element would be the tag <w3m-wallet-button name="MetaMask"
shadow_element = driver.find_element(By.CSS_SELECTOR, 'w3m-wallet-button[name="MetaMask"]').shadow_root
WebDriverWait(shadow_element, 10).until(EC.element_to_be_clickable((By.TAG_NAME, 'button'))).click()
Import the required modules:
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
[UPDATE]:
- Various elements on this website are embedded inside the
shadow-root
. - for example, your target/desired button is embedded in a 5-layer nested
shadow-root
Here's the complete working solution:
import time
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
options = ChromeOptions()
options.add_argument("--start-maximized")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 10)
url = "https://wallet.polygon.technology/?redirectOnConnect=zkEVM_bridge"
driver.get(url)
# click on the "Connect to a Wallet" button
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.navbar__apps-section__auth__login"))).click()
time.sleep(2)
driver.execute_script("""document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();""")
time.sleep(5)
- After clicking on the <kbd>Connect to a Wallet</kbd>, we wait for 1-2 seconds just to make sure that the overlay window is visibly present, although it appears very quickly.
- The used javascript query to locate and click on the desired button
document.querySelector('w3m-modal').shadowRoot.querySelector('w3m-modal-router').shadowRoot.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-modal-footer').querySelectorAll('w3m-wallet-button')[0].shadowRoot.querySelector('button').click();
will click on the very first wallet, if you like to click on the 2nd or 3rd wallet option, just simply replace the
querySelectorAll('w3m-wallet-button')[0]
withquerySelectorAll('w3m-wallet-button')[1]
orquerySelectorAll('w3m-wallet-button')[2]
respectively in the above-mentioned javascript query.
答案2
得分: 1
<button>
元素位于多个 #shadow-root (open) 内。
解决方案
要单击带有文本 MetaMask 的按钮,您需要使用 WebDriverWait 来等待 element_to_be_clickable(),您可以使用以下 locator strategy:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((driver.execute_script("return document.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-wallet-button').shadowRoot.querySelector('button > div > w3m-text.w3m-sublabel')")))).click()
注意:您必须添加以下导入:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
英文:
The <button>
element is within multiple #shadow-root (open)
Solution
To click on button with text MetaMask you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following locator strategy:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((driver.execute_script("return document.querySelector('w3m-connect-wallet-view').shadowRoot.querySelector('w3m-desktop-wallet-selection').shadowRoot.querySelector('w3m-wallet-button').shadowRoot.querySelector('button > div > w3m-text.w3m-sublabel')")))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论