代码之家  ›  专栏  ›  技术社区  ›  Yoda ESG

如何使用Chrome和geckowebdriver清除浏览器缓存?

  •  0
  • Yoda ESG  · 技术社区  · 6 年前

    How to automate shadow DOM elements using selenium? 与…共事 #shadow-root (open)

    在确定目标位置的过程中 清除数据 按钮在 清除浏览资料 访问url时出现的弹出窗口 chrome://settings/clearBrowserData 通过 我找不到以下元素:

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

    快照:

    settings-privacy-page

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

    • 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
        
    • 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);
    

    expand_shadow_element()

    0 回复  |  直到 6 年前
        1
  •  39
  •   supputuri    7 年前

    如果您试图获取“Clear Data”元素,那么您可以使用下面的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

    注:我们将参考图中所示的术语。所以请仔细看这张图以便更好地理解。

    为了与 阴影元素 shadow host 阴影dom所附加到的。下面是基于shadowHost获取阴影根的简单方法。

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

    然后可以使用shadowRoot元素访问shadowtree元素。

    // 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()
    

    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

        2
  •  1
  •   Pushkar    7 年前

    我不得不做一个类似的测试,需要清除浏览chrome历史记录。一个小的区别是,我在进入弹出窗口的高级部分后清除了数据。当你努力只点击“清除数据”按钮时,我很确定你错漏了一两个层次结构元素。或者可能混淆了兄弟元素和父元素。通过查看您的代码,我假设您已经知道,要访问特定的shadowdom元素,您需要正确的排序,并且上面已经很好地解释了这一点。
    现在就来解决您的问题,这里是我的代码片段,它工作正常。代码将等待数据被清除,然后继续执行下一个操作-

    public WebElement expandRootElement(WebElement element) {
    WebElement ele = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot",
            element);
    return ele;
    }
    
    public void clearBrowsingHistory() throws Exception {
    
        WebDriverWait wait = new WebDriverWait(driver, 15);
        driver.get("chrome://settings/clearBrowserData");
    // Get shadow root elements
        WebElement shadowRoot1 = expandRootElement(driver.findElement(By.xpath("/html/body/settings-ui")));
    
        WebElement root2 = shadowRoot1.findElement(By.cssSelector("settings-main"));
        WebElement shadowRoot2 = expandRootElement(root2);
    
        WebElement root3 = shadowRoot2.findElement(By.cssSelector("settings-basic-page"));
        WebElement shadowRoot3 = expandRootElement(root3);
    
        WebElement root4 = shadowRoot3
            .findElement(By.cssSelector("#advancedPage > settings-section > settings-privacy-page"));
        WebElement shadowRoot4 = expandRootElement(root4);
    
        WebElement root5 = shadowRoot4.findElement(By.cssSelector("settings-clear-browsing-data-dialog"));
        WebElement shadowRoot5 = expandRootElement(root5);
    
        WebElement root6 = shadowRoot5
            .findElement(By.cssSelector("cr-dialog div[slot ='button-container'] #clearBrowsingDataConfirm"));
    
        root6.click();
        wait.until(ExpectedConditions.invisibilityOf(root6));
    }
    

    我也在这里添加了屏幕快照- image

        3
  •  0
  •   undetected Selenium    5 年前

    Locator Strategy document.querySelector() 工作完美通过

    但是,当所需的元素从 你需要诱导 WebDriverWait网站 对于 elementToBeClickable() 您可以使用以下解决方案:

    • 代码块:

      driver.get("chrome://settings/clearBrowserData");
      new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable((WebElement) ((JavascriptExecutor)driver).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')"))).click();
      System.out.println("Clear data Button Clicked");
      
    • 控制台输出:

      Clear data Button Clicked