【问题标题】:Get WebDriver of already opened Chrome Browser获取已经打开的 Chrome 浏览器的 WebDriver
【发布时间】:2020-07-25 10:43:11
【问题描述】:

我想要一个已经打开的浏览器(如 Chrome)的 IWebDriver。因为那时我需要自动执行表单身份验证和/或基本身份验证。

我以为是这个

IWebDriver driver = new RemoteWebDriver(new System.Uri("http://localhost:4445/wd/hub"), new ChromeOptions());

可以解决问题,但它只会打开另一个 chrome 窗口。相反,我想“阅读”一个已经打开的。

硒可以吗?或者我应该使用另一个库吗?

【问题讨论】:

标签: c# selenium selenium-chromedriver


【解决方案1】:

根据 Selenium 问题页面: https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/18

问题已关闭并标记为不可行 连接到现有浏览器的过程将基于每个浏览器。 在 IE 中做这件事可能很容易,但在 Chrome 或 Firefox 中做就会有问题。

例如: Chrome 实际上通过网络 / tcp json 请求从 Selenium 接收命令到特定端口。 当 Selenium 驱动程序停止运行时 - 它会丢失 Chrome 调试端口的端口号。 端口可能仍处于打开状态,但可能介于 10000 和 30000 之间等

即使你为 Chrome 解决了这个问题,它也需要另一个为 Firefox 定制的解决方案。

除非您的身份验证有“Captcha”或机器人检查,否则我建议您只自动化身份验证阶段。 一般来说 - 自动化测试是独立的,不依赖外部干扰或外部测试是一种很好的做法。

浏览器应在测试开始时启动并在测试结束时终止。

假设您使用 Selenium 进行测试而不是出于恶意目的。

硒在这个阶段对你没有帮助。

但是,如果您可以在 Chrome 而不是其他浏览器上接受您的答案/解决方案。

public static Chrome StartChromeDriver(int port)
        {
            try
            {
                string Path = Registry.Installation.GetChromeExecutable();
                Process p = new Process();
                ProcessStartInfo psi = new ProcessStartInfo(Path);
                string args = "--remote-debugging-port="+ port.ToString()+" --user-data-dir=remote-profile";
                psi.Arguments = args;
                psi.Verb = "runas";
                p.StartInfo = psi;

                p.Start();

                return new Chrome("http://localhost:" + port.ToString());
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.ToString());
                return null;
            }
        }

这将启动一个 chrome 进程,并将调试端口打开到您提供的数字。 (您可以对此进行跟踪,并重新连接并重新向正在运行的 chrome 实例发出命令)

public dynamic EnablePage()
        {
           json = @"{""id"":12345,""method"":""Page.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }
        public dynamic EnableRuntime()
        {
            json = @"{""id"":12345,""method"":""Runtime.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }
        public dynamic EnableNetwork()
        {
            json = @"{""id"":12345,""method"":""Network.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }

这是一些我躺在那里的代码。 有一天我很无聊,决定用 Chrome 自动化重新发明轮子。基本上 - 这段代码是你如何在不使用 Selenium 的情况下自动化 Chrome。 它确实依赖于 WebSockets4Net 但话虽如此 - 它可能会被重构为使用 TcpClient。 向 Chrome 发出的所有命令都是以 json 请求的形式完成的。

例如:以下 json 命令将告诉 chrome 执行以下 javascript - 本质上是导航到提供的 url。

{
    "method": "Runtime.evaluate",
    "params": {
        "expression": "document.location='urlhere'",
        "objectGroup": "console",
        "includeCommandLineAPI": true,
        "doNotPauseOnExceptions": false,
        "returnByValue": false
    },
    "id": 1
}


public dynamic SendCommand(string cmd)
        {
            if (EventHandler == null)
            {
                EventHandler = new Events();
                EventHandler.OnNavigateStart += new Events.OnPageNavigateStart(EventHandler_OnNavigateStart);
                EventHandler.OnNavigateEnd += new Events.OnPageNavigateEnded(EventHandler_OnNavigateEnd);
            }
            WebSocket4Net.WebSocket j = new WebSocket4Net.WebSocket(this.sessionWSEndpoint);
            ManualResetEvent waitEvent = new ManualResetEvent(false);
            ManualResetEvent closedEvent = new ManualResetEvent(false);
            dynamic message = null;
            byte[] data;

            Exception exc = null;
            j.Opened += delegate(System.Object o, EventArgs e)
            {
                j.Send(cmd);
            };

            j.MessageReceived += delegate(System.Object o, WebSocket4Net.MessageReceivedEventArgs e)
            {
                message = e.Message;
                EventHandler.ParseEvents(e);
                waitEvent.Set();

            };

            j.Error += delegate(System.Object o, SuperSocket.ClientEngine.ErrorEventArgs e)
            {
                exc = e.Exception;
                waitEvent.Set();
            };

            j.Closed += delegate(System.Object o, EventArgs e)
            {
                closedEvent.Set();
            };

            j.DataReceived += delegate(object sender, WebSocket4Net.DataReceivedEventArgs e)
            {
                data = e.Data;
                waitEvent.Set();
            };

            j.Open();

            waitEvent.WaitOne();
            if (j.State == WebSocket4Net.WebSocketState.Open)
            {
                j.Close();
                closedEvent.WaitOne();
                j = null;
            }

            if (exc != null)
                throw exc;
            serializer = null;
            serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { converter });

            dynamic obj = serializer.Deserialize(message, typeof(object));
            message = null;
            data = null;
            return obj;
        }

为了演示如何实际使用它 - 您可以实现页面对象并创建将对象封装在屏幕上的“类型”。

例如:

public class Link : Base.Element
    {
        public Link(string XPath)
        {
            this.XPath = String.Copy(XPath);
        }

        /// <summary>
        /// Overriding it - just in case we need to handle clicks differently
        /// </summary>
        /// <returns></returns>
        public virtual bool Click()
        {

            Sync();
            Console.WriteLine(Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).click();"));
            return true;
        }

        public virtual bool WaitForExistance(int iTimeout)
        {
            return base.WaitForExistance(iTimeout);
        }

        public virtual bool Exists()
        {

            return base.Exists();
        }


        public virtual string GetText()
        {
            Sync();
            dynamic dval =  Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).innerText");
            return dval.result.result.value;
        }
    }

请注意 - 当我使用此代码时,WebSockets4Net 中存在内存泄漏 - 因此最终必须重新启动应用程序。 也许如果 WebSockets4Net 被移除和替换 - 它会更好地工作。

【讨论】:

  • 我的公司希望自动执行身份验证过程,因此我们需要在已打开的页面和浏览器自动启动时都执行此操作。然后我需要找到另一个图书馆。谢谢。
  • 您的身份验证系统是否复杂到 Selenium 无法完成?在任何情况下——如果你下定决心要努力做到这一点,我建议你让你的问题变得简单。你能忍受一个浏览器上的解决方案吗?如果是这样 - 我建议通过调试协议查看 Chrome 自动化。
  • 我添加了一些我一直在使用的代码——基本上在过去,我为完全没有 Selenium 的 Chrome 开发了自己的自动化代码。这将允许您重新连接到现有的 Chrome 窗口 - 假设该窗口是在打开调试端口的情况下打开的。
  • 问题不是身份验证问题是识别已经打开的 chrome 浏览器。我会试试你的解决方案,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 1970-01-01
  • 2013-04-04
  • 1970-01-01
  • 2012-04-08
  • 2023-02-17
  • 1970-01-01
相关资源
最近更新 更多