Selenium 读取 DOM 速度极慢

标签 selenium selenium-webdriver webdriver selenium-firefoxdriver firefox-driver

Selenium 与 DOM 的交互似乎非常缓慢,而在每个页面实例化中都做一些事情。在整个站点中,我们都有可见的微调器,指示任何 Unresolved API 调用是否已解决。总之,我有三种方法可以在执行任何操作之前确保页面的稳定性。

  • 检查 DOM 就绪状态
  • 检查任何未完成的 JQuery 调用
  • 检查加载微调器

  • 所有这三个都是通过以下方法作为页面对象实例化的一部分完成的。
        public static void waitForLoadingAllSpinnersAnywhere(final WebDriver driver){
        final WebDriverWait wait = new WebDriverWait(driver, timeout);
        
        wait.until(waitForDomReadyState());
        wait.until(waitForjQueryToBeInactive());
        List<WebElement> elements = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(spinnersLoacator));
        
        for(WebElement element: elements){
            wait.until(invisibilityOfElementLocated(element));  
         }
        }
    
        private static ExpectedCondition<Boolean> waitForDomReadyState(){
    
            return new ExpectedCondition<Boolean>() {
    
                @Override
                public Boolean apply(WebDriver d){
    
                    return ( ((JavascriptExecutor) d).executeScript("return document.readyState;").equals("complete"));
                }
            };
        }
    
    
        private static ExpectedCondition<Boolean> waitForjQueryToBeInactive(){
    
            return new ExpectedCondition<Boolean>() {
    
                @Override
                public Boolean apply(WebDriver d){
    
                    return (Boolean) ( ((JavascriptExecutor) d).executeScript("return jQuery.active == 0;"));
                }
            };
        }
    
        public static ExpectedCondition<Boolean> invisibilityOfElementLocated(final WebElement element){
    
            return new ExpectedCondition<Boolean>() {
    
                @Override
                public Boolean apply(WebDriver driver){
    
                    try{
                        return !element.isDisplayed();
                    } catch (NoSuchElementException | StaleElementReferenceException e){
                        // Returns true because the element is not present in DOM.
                        // The
                        // try block checks if the element is present but is
                        // invisible or stale
                        return true;
                    }
                }
            };
        }
    
    以具有大量 API 调用并获取大量数据的页面(例如患者页面)为例。对于初始类实例化,大约需要 17 秒(日志如下)。我的 Selenium 知识表明,后续页面实例化不应花费相同或更多时间来检查 DOM 就绪状态,或者 JQuery 调用或微调器等待,因为根本没有任何变化。但是,每次新页面实例化时,我都会看到检查所有这三个页面所花费的时间相同。那里发生了什么?每次我执行这些操作时,Selenium 是否实际上都尝试与服务器交互,或者由于某种原因,与客户端的交互速度很慢?如果是这样,可能的答案是什么?

    Console log

    ==== [[Finished waiting for 8 spinner elements found on widget [Patient] after [17] s]]

    ==== [[Start waiting for 8 spinner elements found on widget [Patient] ]]

    ==== [[Finished waiting for 8 spinner elements found on widget [Patient] after [17] s]]

    ==== Browser on [[[Patient]]]

    ==== [[Start waiting for 8 spinner elements found on widget [Patient] ]]

    ==== [[Finished waiting for 8 spinner elements found on widget [Patient] after [17] s]]


    环境:
  • Selenium 2.48
  • 火狐 38

  • 我也尝试过使用 Selenium 2.52 和 firefox 44,结果相同

    最佳答案

    Selenium 处理客户端的所有等待,每次评估都向服务器发送请求,直到满足条件。
    在高延迟的情况下,它会迅速退化,尤其是在有很多调用的情况下。此外,一些评估需要脚本注入(inject),这也无济于事。

    因此,在您的情况下提高性能的最佳方法是使用单个异步 JavaScript 调用:

    public static void waitForLoadingAllSpinnersAnywhere(final WebDriver driver) {
      const String JS_WAIT_SPINNERS = 
          "var callback = arguments[0]; " +
          "(function fn(){ " +
          "  if (document.readyState == 'complete' && jQuery.active == 0) { " +
          "    var elts = $('.spinners'); " +
          "    if (elts.length == 8 && !elts.is(':visible')) " +
          "      return callback(); " +
          "  } " +
          "  setTimeout(fn, 60); " +
          "})();";
    
       ((JavascriptExecutor)driver).executeAsyncScript(JS_WAIT_SPINNERS);
    }
    

    初始化超时:
    driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
    

    关于Selenium 读取 DOM 速度极慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35448431/

    相关文章:

    java - Selenium 自动元素点击返回 null

    java - 使用 geckodriver 时遇到 HttpHostConnectException

    selenium-webdriver - Protractor - 在执行下一步之前等待异步 promise

    python - 使用 python 在已打开的对话框中选择一个文件

    Java:通过运行时修改系统属性

    vb.net - 使 Selenium Firefox Webdriver 信任根证书

    java - 通过系统属性检查是否安装了 FirefoxDriver 或 ChromeDriver?

    python - 如何通过xpath提取html dom内文本节点的文本?

    python - 如何使用 Selenium 2-WebDriver 的 Python 绑定(bind)最大化浏览器窗口?

    google-chrome - Protractor woant 运行我的脚本