¿Puede Selenium interactuar con una sesión de navegador existente?

¿Alguien sabe si Selenium (WebDriver preferiblemente) puede comunicarse y actuar a través de un navegador que ya se está ejecutando antes de iniciar un Selenium Client?

Me refiero a si Selenium es capaz de comunicarse con un navegador sin usar el Servidor Selenium (podría ser un Internet Explorer lanzado manualmente, por ejemplo).

Esta es una solicitud de función bastante antigua: permite que el controlador de web se conecte a un navegador en ejecución . Entonces oficialmente no es compatible.

Sin embargo, hay algunos códigos de trabajo que dicen apoyar esto: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/ .

Esta es una respuesta duplicada ** Vuelva a conectar a un controlador en python selenium ** Esto es aplicable en todos los controladores y para Java api.

  1. abrir un controlador

    driver = webdriver.Firefox() #python 
  2. extrae a session_id y _url del objeto del controlador.

     url = driver.command_executor._url #"http://127.0.0.1:60622/hub" session_id = driver.session_id #'4e167f26-dc1d-4f51-a207-f761eaf73c31' 
  3. Use estos dos parámetros para conectarse a su controlador.

     driver = webdriver.Remote(command_executor=url,desired_capabilities={}) driver.session_id = session_id 

    Y está conectado a su controlador nuevamente.

     driver.get("http://www.mrsmart.in") 

Es posible. Pero tienes que hackearlo un poco, hay un código. Lo que tienes que hacer es ejecutar el servidor autónomo y el “parche” RemoteWebDriver

 public class CustomRemoteWebDriver : RemoteWebDriver { public static bool newSession; public static string capPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionCap"); public static string sessiodIdPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionid"); public CustomRemoteWebDriver(Uri remoteAddress) : base(remoteAddress, new DesiredCapabilities()) { } protected override Response Execute(DriverCommand driverCommandToExecute, Dictionary parameters) { if (driverCommandToExecute == DriverCommand.NewSession) { if (!newSession) { var capText = File.ReadAllText(capPath); var sidText = File.ReadAllText(sessiodIdPath); var cap = JsonConvert.DeserializeObject>(capText); return new Response { SessionId = sidText, Value = cap }; } else { var response = base.Execute(driverCommandToExecute, parameters); var dictionary = (Dictionary) response.Value; File.WriteAllText(capPath, JsonConvert.SerializeObject(dictionary)); File.WriteAllText(sessiodIdPath, response.SessionId); return response; } } else { var response = base.Execute(driverCommandToExecute, parameters); return response; } } } 

Este fragmento permite volver a utilizar la instancia del navegador existente sin tener que subir el navegador duplicado. Encontrado en el blog de Tarun Lalwani .

 from selenium import webdriver from selenium.webdriver.remote.webdriver import WebDriver # executor_url = driver.command_executor._url # session_id = driver.session_id def attach_to_session(executor_url, session_id): original_execute = WebDriver.execute def new_command_execute(self, command, params=None): if command == "newSession": # Mock the response return {'success': 0, 'value': None, 'sessionId': session_id} else: return original_execute(self, command, params) # Patch the function before creating the driver object WebDriver.execute = new_command_execute driver = webdriver.Remote(command_executor=executor_url, desired_capabilities={}) driver.session_id = session_id # Replace the patched function with original function WebDriver.execute = original_execute return driver bro = attach_to_session('http://127.0.0.1:64092', '8de24f3bfbec01ba0d82a7946df1d1c3') bro.get('http://ya.ru/') 

Todas las soluciones hasta ahora carecían de cierta funcionalidad. Aquí está mi solución:

 public class AttachedWebDriver extends RemoteWebDriver { public AttachedWebDriver(URL url, String sessionId) { super(); setSessionId(sessionId); setCommandExecutor(new HttpCommandExecutor(url) { @Override public Response execute(Command command) throws IOException { if (command.getName() != "newSession") { return super.execute(command); } return super.execute(new Command(getSessionId(), "getCapabilities")); } }); startSession(new DesiredCapabilities()); } } 

Solución de Javascript:

Me he conectado exitosamente a una sesión de navegador existente usando esta función

 webdriver.WebDriver.attachToSession(executor, session_id); 

La documentación se puede encontrar aquí .

Obtuve una solución en python, modifiqué la clase de webdriver basada en la clase PersistenBrowser que encontré.

https://github.com/axelPalmerin/personal/commit/fabddb38a39f378aa113b0cb8d33391d5f91dca5

reemplace el módulo del controlador web /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py

Ej. usar:

 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities runDriver = sys.argv[1] sessionId = sys.argv[2] def setBrowser(): if eval(runDriver): webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME, ) else: webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub', desired_capabilities=DesiredCapabilities.CHROME, session_id=sessionId) url = webdriver.command_executor._url session_id = webdriver.session_id print url print session_id return webdriver 

Estoy usando Rails + Cucumber + Selenium Webdriver + PhantomJS, y he estado usando una versión parcheada de Selenium Webdriver, que mantiene el navegador PhantomJS abierto entre las ejecuciones de prueba. Vea esta publicación en el blog: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

Véase también mi respuesta a esta publicación: ¿Cómo ejecuto un comando en un navegador ya abierto desde un archivo ruby?

Esto es bastante fácil usando el cliente JavaScript selenium-webdriver :

Primero, asegúrese de tener un servidor WebDriver ejecutándose. Por ejemplo, descargue ChromeDriver , luego ejecute chromedriver --port=9515 .

En segundo lugar, crea el controlador de esta manera :

 var driver = new webdriver.Builder() .withCapabilities(webdriver.Capabilities.chrome()) .usingServer('http://localhost:9515') // <- this .build(); 

Aquí hay un ejemplo completo:

var webdriver = require ('selenium-webdriver');

 var driver = new webdriver.Builder() .withCapabilities(webdriver.Capabilities.chrome()) .usingServer('http://localhost:9515') .build(); driver.get('http://www.google.com'); driver.findElement(webdriver.By.name('q')).sendKeys('webdriver'); driver.findElement(webdriver.By.name('btnG')).click(); driver.getTitle().then(function(title) { console.log(title); }); driver.quit(); 

Inspirado por la respuesta de Eric, aquí está mi solución a este problema para el selenium 3.7.0. Comparado con la solución en http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/ , la ventaja es que no habrá una ventana en blanco cada vez que me conecte a la sesión existente.

 import warnings from selenium.common.exceptions import WebDriverException from selenium.webdriver.remote.errorhandler import ErrorHandler from selenium.webdriver.remote.file_detector import LocalFileDetector from selenium.webdriver.remote.mobile import Mobile from selenium.webdriver.remote.remote_connection import RemoteConnection from selenium.webdriver.remote.switch_to import SwitchTo from selenium.webdriver.remote.webdriver import WebDriver # This webdriver can directly attach to an existing session. class AttachableWebDriver(WebDriver): def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities=None, browser_profile=None, proxy=None, keep_alive=False, file_detector=None, session_id=None): """ Create a new driver that will issue commands using the wire protocol. :Args: - command_executor - Either a string representing URL of the remote server or a custom remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'. - desired_capabilities - A dictionary of capabilities to request when starting the browser session. Required parameter. - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. Optional. - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will be started with given proxy settings, if possible. Optional. - keep_alive - Whether to configure remote_connection.RemoteConnection to use HTTP keep-alive. Defaults to False. - file_detector - Pass custom file detector object during instantiation. If None, then default LocalFileDetector() will be used. """ if desired_capabilities is None: raise WebDriverException("Desired Capabilities can't be None") if not isinstance(desired_capabilities, dict): raise WebDriverException("Desired Capabilities must be a dictionary") if proxy is not None: warnings.warn("Please use FirefoxOptions to set proxy", DeprecationWarning) proxy.add_to_capabilities(desired_capabilities) self.command_executor = command_executor if type(self.command_executor) is bytes or isinstance(self.command_executor, str): self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive) self.command_executor._commands['GET_SESSION'] = ('GET', '/session/$sessionId') # added self._is_remote = True self.session_id = session_id # added self.capabilities = {} self.error_handler = ErrorHandler() self.start_client() if browser_profile is not None: warnings.warn("Please use FirefoxOptions to set browser profile", DeprecationWarning) if session_id: self.connect_to_session(desired_capabilities) # added else: self.start_session(desired_capabilities, browser_profile) self._switch_to = SwitchTo(self) self._mobile = Mobile(self) self.file_detector = file_detector or LocalFileDetector() self.w3c = True # added hardcoded def connect_to_session(self, desired_capabilities): response = self.execute('GET_SESSION', { 'desiredCapabilities': desired_capabilities, 'sessionId': self.session_id, }) # self.session_id = response['sessionId'] self.capabilities = response['value'] 

Para usarlo:

 if use_existing_session: browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip), desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER), session_id=session_id) self.logger.info("Using existing browser with session id {}".format(session_id)) else: browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip), desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER)) self.logger.info('New session_id : {}'.format(browser.session_id)) 

Parece que esta característica no es oficialmente compatible con el selenium. Sin embargo, Tarun Lalwani ha creado un código Java funcional para proporcionar la función. Consulte: http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/

Aquí está el código de muestra de trabajo, copiado del enlace de arriba:

 public static RemoteWebDriver createDriverFromSession(final SessionId sessionId, URL command_executor){ CommandExecutor executor = new HttpCommandExecutor(command_executor) { @Override public Response execute(Command command) throws IOException { Response response = null; if (command.getName() == "newSession") { response = new Response(); response.setSessionId(sessionId.toString()); response.setStatus(0); response.setValue(Collections.emptyMap()); try { Field commandCodec = null; commandCodec = this.getClass().getSuperclass().getDeclaredField("commandCodec"); commandCodec.setAccessible(true); commandCodec.set(this, new W3CHttpCommandCodec()); Field responseCodec = null; responseCodec = this.getClass().getSuperclass().getDeclaredField("responseCodec"); responseCodec.setAccessible(true); responseCodec.set(this, new W3CHttpResponseCodec()); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } else { response = super.execute(command); } return response; } }; return new RemoteWebDriver(executor, new DesiredCapabilities()); } public static void main(String [] args) { ChromeDriver driver = new ChromeDriver(); HttpCommandExecutor executor = (HttpCommandExecutor) driver.getCommandExecutor(); URL url = executor.getAddressOfRemoteServer(); SessionId session_id = driver.getSessionId(); RemoteWebDriver driver2 = createDriverFromSession(session_id, url); driver2.get("http://tarunlalwani.com"); } 

Su prueba debe tener un RemoteWebDriver creado a partir de una sesión de navegador existente. Para crear ese controlador, solo necesita conocer la “información de la sesión”, es decir, la dirección del servidor (local en nuestro caso) donde se está ejecutando el navegador y la identificación de la sesión del navegador. Para obtener estos detalles, podemos crear una sesión de navegador con selenium, abrir la página deseada y finalmente ejecutar el script de prueba real.

No sé si hay una forma de obtener información de sesión para una sesión que no fue creada por el selenium.

Aquí hay un ejemplo de información de la sesión:

Dirección del servidor remoto: http: // localhost: 24266 . El número de puerto es diferente para cada sesión. ID de sesión: 534c7b561aacdd6dc319f60fed27d9d6.

    Intereting Posts