gpt4 book ai didi

java - 使用cssSelector清除Chrome浏览器的浏览数据时,如何与#shadow-root(打开)中的元素进行交互

转载 作者:行者123 更新时间:2023-12-02 03:57:49 24 4
gpt4 key购买 nike

我一直在讨论How to automate shadow DOM elements using selenium?以使用#shadow-root (open)元素。

在通过Selenium访问url chrome://settings/clearBrowserData时出现的“清除浏览数据”弹出窗口中找到“清除数据”按钮的过程中,我无法找到以下元素:

#shadow-root (open)
<settings-privacy-page>


快照:

settings-privacy-page

使用 Selenium以下是我的代码试用以及遇到的相关错误:


尝试1:

WebElement root5 = shadow_root4.findElement(By.tagName("settings-privacy-page"));



错误:

Exception in thread "main" org.openqa.selenium.JavascriptException: javascript error: b.getElementsByTagName is not a function


尝试2:

WebElement root5 = shadow_root4.findElement(By.cssSelector("settings-privacy-page"));



错误:

Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"settings-privacy-page"}


尝试3:

WebElement root5 = (WebElement)((JavascriptExecutor)shadow_root4).executeScript("return document.getElementsByTagName('settings-privacy-page')[0]");



错误:

Exception in thread "main" java.lang.ClassCastException: org.openqa.selenium.remote.RemoteWebElement cannot be cast to org.openqa.selenium.JavascriptExecutor




如果有帮助的话,初始代码块(至上一行)可以完美工作:

driver.get("chrome://settings/clearBrowserData");
WebElement root1 = driver.findElement(By.tagName("settings-ui"));
WebElement shadow_root1 = expand_shadow_element(root1);

WebElement root2 = shadow_root1.findElement(By.cssSelector("settings-main#main"));
WebElement shadow_root2 = expand_shadow_element(root2);

WebElement root3 = shadow_root2.findElement(By.cssSelector("settings-basic-page[role='main']"));
WebElement shadow_root3 = expand_shadow_element(root3);

WebElement root4 = shadow_root3.findElement(By.cssSelector("settings-section[page-title='Privacy and security']"));
WebElement shadow_root4 = expand_shadow_element(root4);


PS: expand_shadow_element()的工作无懈可击。

最佳答案

如果您尝试获取“清除数据”元素,则可以使用下面的js获取该元素然后执行。

return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')


这是示例脚本。

driver.get("chrome://settings/clearBrowserData");
driver.manage().window().maximize();
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
// now you can click on clear data button
clearData.click();


编辑2:解释

问题:Selenium不提供与 Shadow DOM elements一起使用的明确支持,因为它们不在当前dom中。这就是为什么当尝试访问 NoSuchElementException中的元素时会出现 shadow dom异常的原因。

影子DOM:
enter image description here

注意:我们将参考图片中显示的术语。因此,请仔细阅读图片以更好地理解。

解:

为了首先使用阴影元素,我们必须找到阴影dom附加到的 shadow host。这是基于shadowHost获取影子根的简单方法。

private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}


然后,您可以使用shadowRoot元素访问阴影树元素。

// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));


为了简化上述所有步骤,创建了以下方法。

public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
WebElement shardowRoot = getShadowRoot(driver, shadowHost);
return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}


现在您可以通过单个方法调用获取shadowTree元素

WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");


并像往常一样执行 .click().getText()等操作。

shadowTreeElement.click()


当您只有一个级别的影子DOM时,这看起来很简单。但是在这里,在这种情况下,我们有多个级别的阴影域。因此,我们必须通过到达每个影子主机和根来访问元素。
enter image description here

以下是使用上述方法的代码段(getShadowElement和getShadowRoot)

// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("settings-ui"));

// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "settings-main");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"settings-basic-page");
WebElement shadowElementL3 = getShadowElement(driver, shadowElementL2,"settings-section > settings-privacy-page");
WebElement shadowElementL4 = getShadowElement(driver, shadowElementL3,"settings-clear-browsing-data-dialog");
WebElement shadowElementL5 = getShadowElement(driver, shadowElementL4,"#clearBrowsingDataDialog");
WebElement clearData = shadowElementL5.findElement(By.cssSelector("#clearBrowsingDataConfirm"));
System.out.println(clearData.getText());
clearData.click();


您可以按照答案开头所述在单个js调用中实现上述所有步骤(以下添加只是为了减少混乱)。

WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");


屏幕截图:
enter image description here

关于java - 使用cssSelector清除Chrome浏览器的浏览数据时,如何与#shadow-root(打开)中的元素进行交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56749619/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com