【问题标题】:Selenium. Bring-up window on the front硒。前面的弹出窗口
【发布时间】:2018-06-22 23:05:52
【问题描述】:

如果您运行以下代码,那么在循环的每次迭代中,浏览器都会在前面显示并获得焦点。

public class Program
{
  private static void Main()
  {
    var driver = new ChromeDriver();
    driver.Navigate().GoToUrl("https://i.imgur.com/cdA7SBB.jpg");
    for (int i = 0; i < 100; i++)
    {
      var ss = ((ITakesScreenshot)driver).GetScreenshot();
      ss.SaveAsFile("D:/imgs/i.jpg");
    }
  }
}

问题是:为什么会发生这种情况,可以将其关闭吗?无头模组不适合。

这似乎总是在 Selenium 需要保存/读取文件或启动进程时发生。

【问题讨论】:

  • Selenium 需要焦点才能与 DOM 元素交互。你到底想turn off做什么?
  • @DebanjanB,粗略地说,我希望浏览器不干扰我,我也不想使用无头模式。
  • 试图了解您的用例,如果不是WebPage 或任何WebElement,您要为哪个对象获取Screenshot

标签: c# selenium selenium-webdriver


【解决方案1】:

要截屏,chromedriver 会激活窗口。这是设计使然,即使技术上可行,也无法避免。 有关相关来源,请查看window_commands.cc

但是,您可以通过将窗口移到屏幕外来避免这种影响:

driver.Manage().Window.Position = new Point(-32000, -32000);

或通过在屏幕外启动浏览器:

var options = new ChromeOptions();
options.AddArgument("--window-position=-32000,-32000");

更新

您可以通过 devtool API 直接截取屏幕截图来避免激活。这是一个覆盖GetScreenshot的类:

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Remote;
using JObject = System.Collections.Generic.Dictionary<string, object>;


class ChromeDriverEx : ChromeDriver
{
    public ChromeDriverEx(ChromeOptions options = null) 
        : base(options ?? new ChromeOptions()) {
        var repo = base.CommandExecutor.CommandInfoRepository;
        repo.TryAddCommand("send", new CommandInfo("POST", "/session/{sessionId}/chromium/send_command_and_get_result"));
    }

    public new Screenshot GetScreenshot() {
        object response = Send("Page.captureScreenshot", new JObject {{"format", "png"}, {"fromSurface", true}});
        string base64 = (string)((JObject)response)["data"];
        return new Screenshot(base64);
    }

    protected object Send(string cmd, JObject args) {
        return this.Execute("send",  new JObject {{"cmd", cmd}, {"params", args}}).Value;
    }
}

用法:

var driver = new ChromeDriverEx();
driver.Url = "https://stackoverflow.com";
driver.GetScreenshot().SaveAsFile("/tmp/screenshot.png");
driver.Quit();

【讨论】:

  • 谢谢回答。此方案隐藏了强迫症浏览器窗口,但并没有解决浏览器窃取焦点的问题。
  • 由于驱动程序不提供该选项,因此您将无法取消激活以开箱即用。你有两个选择。使用修改后的 window_commands.cc. 重建 chromedriver 或扩展 ChromeDriver 以通过 devtools 协议直接截取屏幕截图。您将找到一个使用 Java/Python here 的示例。
  • 你知道为什么 chromedriver 开发者设计了“抓握焦点”解决方案,现在我不明白为什么 chrome driver 需要焦点来截图?
  • 失去焦点时页面可能会改变其内容。请记住,Selenium 主要是为测试而设计的。因此,对未激活的窗口进行截图并没有什么意义。
  • 绝妙的答案,这正是我所需要的。非常感谢。
【解决方案2】:

当您通过Automation 脚本调用Navigate().GoToUrl("url") 方法时,预计您的脚本将与网页上的某些元素进行交互。因此,Selenium 要与这些元素进行交互,Selenium 需要专注。因此打开浏览器拉到最前面获得焦点是通过Navigate().GoToUrl("url")实现的默认现象。

现在 Default ModeHeadless ModeChromeOption/FirefoxOptions 控制在初始化WebDriver 实例时作为参数传递的类,并将调用Navigate().GoToUrl("url")。因此,Navigate().GoToUrl("url") 不会影响WebDriver 实例如何控制Mode of Operation,即Default ModeHeadless Mode

现在,当您尝试从 ITakesScreenshot Interface 调用方法时,即 ITakesScreenshot.GetScreenshot Method 定义为:

Gets a Screenshot object representing the image of the page on the screen.

如果WebDriver 实例扩展了ITakesScreenshot,请根据浏览器尽最大努力按优先顺序返回以下内容:

  1. Entire page
  2. Current window
  3. Visible portion of the current frame
  4. The screenshot of the entire display containing the browser

在某些情况下,浏览器可能会失去焦点。在这种情况下,您可以使用IJavascriptExecutor 重新获得焦点,如下所示:

((IJavascriptExecutor) driver).executeScript("window.focus();");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-12
    • 2017-09-28
    • 1970-01-01
    相关资源
    最近更新 更多