【问题标题】:How to stop loading page in Selenium WebDriver when an element is already present?当元素已经存在时,如何停止在 Selenium WebDriver 中加载页面?
【发布时间】:2016-10-13 04:56:40
【问题描述】:

我正在抓取一个网站,由于某种原因需要 15 秒才能加载,但我需要的元素会在前 5 秒内加载。

问题是,当代码已经存在时,我可以停止加载页面并继续使用代码吗?

当前代码:

driver.Navigate().GoToUrl(url);

new WebDriverWait(driver, TimeSpan.FromSeconds(20))
    .Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath)));

当前行为:

  1. 我打电话给driver.Navigate().GoToUrl(url);
  2. 驱动程序开始加载页面
  3. 元素出现在大约5 秒(那时我想继续下一条语句)
  4. 驱动程序等待整整 15 秒以完全加载页面
  5. 然后驱动程序最终转到WebDriverWait 函数

问题:

类似问题中的所有解决方案都是在页面完全加载后调用的,使得答案毫无用处。

我能做点什么吗?谢谢。

【问题讨论】:

  • 但是为什么加载页面需要 15 秒?我真的会从提高性能开始
  • 有一个很好的解决方案概述in this answer

标签: c# selenium-webdriver phantomjs


【解决方案1】:

方法 .Navigate().GoToUrl 的创建方式是仅在页面完全加载时才执行下一行。所以是的,你在代码中写什么并不重要,在导航方法之后,它永远不会工作,直到页面完全加载。 作为一种解决方法,您可以选择超时选项,这样它会在页面仍然加载时引发异常,因此我们应该捕获它并执行我们的下一个代码。

//这是java代码,所以请只选择这里的逻辑:
// 将页面加载超时设置为 10 秒。

driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);  

try {  
  driver.Navigate().GoToUrl(url);  
} catch (TimeoutException e) {  
  // Ignore the exception.  
}  

【讨论】:

  • 优秀的答案!这是我一直在寻找的东西。
【解决方案2】:

我也遇到了同样的问题,用谷歌搜索了很多,但没有找到可行的解决方案。超时解决方案不适用于我的情况。最后,似乎真正有效的唯一方法是使用全局钩子。

更多关于hook的信息,请参考这篇优秀的帖子:Global keyboard capture in C# application

所以,在上面链接中的钩子处理代码中,添加如下内容:

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            if (vkCode == 121)  //F10 key
            {
                try
                {
                    UnhookWindowsHookEx(_hookID);//avoid ESC key to be captured
                    SetForegroundWindow(_handle);
                    SendKeys.Send("{ESC}");
                    _hookID = SetHook(_proc);

                }
                catch (Exception ex)
                {
                }
            }
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

相关代码如下:

    using System.Windows.Automation; //you need to reference UIAutomationClient and UIAutomationTypes

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);

    private IntPtr _handle;

    //I forget where I got the code of the function below, probably also from stackoverflow. Thanks to the original author!
    private IntPtr getIntPtrHandle(IWebDriver driver, int timeoutSeconds = 30)
    {
        var end = DateTime.Now.AddSeconds(timeoutSeconds);
        while (DateTime.Now < end)
        {
            // Searching by AutomationElement is a bit faster (can filter by children only)
            var ele = AutomationElement.RootElement;
            foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
            {
                if (!child.Current.Name.Contains(driver.Title)) continue;
                return new IntPtr(child.Current.NativeWindowHandle); ;
            }
        }
        return IntPtr.Zero;
    }

也把 _handle = getIntPtrHandle(webdriver);在你的 webdriver.Navigate().GoToUrl() 语句之前的某个地方。

我测试了上述内容。执行 GoToUrl 后,在某处按 F10(有时两次),页面停止加载。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 2015-10-31
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多