2011-12-01 47 views
26

¿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?¿Puede Selenium interactuar con una sesión de navegador existente?

Quiero decir si Selenium puede comunicarse con un navegador sin usar el Servidor Selenium (podría ser un Internet Explorer iniciado manualmente, por ejemplo).

Respuesta

16

Esta es una solicitud de función muy antigua: Allow webdriver to attach to a running browser. Entonces no es posible en este momento.

+0

Muchas gracias porque en ese enlace que he encontrado una clase que permita hacer eso, pero por desgracia no puedo utilizar esa solución con IE (sólo con Firefox). Voy a lanzar un IEDriver regular y me comunicaré con él desde otros procesos utilizando un middleware. Si tienes una idea de por qué la clase no funciona en IE, te lo agradecería. Gracias. –

8

Es posible. Pero usted tiene que cortar un poco, hay un código Lo que tienes que hacer es ejecutar el servidor de pie solo y "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<string, object> parameters) 
    { 
     if (driverCommandToExecute == DriverCommand.NewSession) 
     { 
      if (!newSession) 
      { 
       var capText = File.ReadAllText(capPath); 
       var sidText = File.ReadAllText(sessiodIdPath); 

       var cap = JsonConvert.DeserializeObject<Dictionary<string, object>>(capText); 
       return new Response 
       { 
        SessionId = sidText, 
        Value = cap 
       }; 
      } 
      else 
      { 
       var response = base.Execute(driverCommandToExecute, parameters); 
       var dictionary = (Dictionary<string, object>) response.Value; 
       File.WriteAllText(capPath, JsonConvert.SerializeObject(dictionary)); 
       File.WriteAllText(sessiodIdPath, response.SessionId); 
       return response; 
      } 
     } 
     else 
     { 
      var response = base.Execute(driverCommandToExecute, parameters); 
      return response; 
     } 
    } 
} 
+3

Basado en esta excelente solución, escribí una publicación de blog completa en la que he discutido cómo conectarme a una instancia de navegador ya abierta de cromo. El código fuente completo también se adjunta en esa publicación de blog. http://binaryclips.com/2015/08/25/selenium-webdriver-in-c-how-to-use-the-existing-window-of-chrome-browser/ – joinsaad

0

estoy usando Rails + pepino + Selenio WebDriver + PhantomJS, y he estado usando una versión parcheada de Selenium Webdriver, que mantiene el navegador PhantomJS abierto entre las ejecuciones de prueba. Ver esta entrada del blog: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

Véase también mi respuesta a este mensaje: How do I execute a command on already opened browser from a ruby file

+0

Gracias por su respuesta –

+0

Si alguien va para rechazar una respuesta, al menos deberían explicar por qué lo hicieron – BringBackCommodore64

0

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

En primer lugar, asegúrese de que tiene un servidor WebDriver ejecución. Por ejemplo, download ChromeDriver, luego ejecute chromedriver --port=9515.

En segundo lugar, crear el conductor like this:

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

Aquí está un ejemplo completo:

var WebDriver = require ('selenio-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(); 
+3

No utiliza la sesión EXISTENTE del navegador. Crea una nueva sesión de chromedriver y abre una nueva ventana del navegador. Y getAllWindowHandles() no mostrará el controlador de la ventana anterior de su navegador. – Dzenly

+0

Actualización: Hay http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebDriver.html#WebDriver.attachToSession Que permite conectarse a la ventana del navegador abierto existente. – Dzenly

16

Ésta es una respuesta duplicado ** Vuelva a conectar a un conductor en selenio pitón ** Esto es aplicable a todos los conductores y para la API de Java.

  1. abrir un conductor

    driver = webdriver.Firefox() #python 
    
  2. extracto a session_id y _url de objeto conductor.

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

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

    Y está conectado de nuevo a su controlador.

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

Esto es exactamente lo que estaba buscando. Gracias. – milso

+2

parece que ya no funciona. – Sajuuk

+0

Funciona para mí, excepto que cada vez que un navegador duplicado está apareciendo. –

2

Todas las soluciones hasta ahora se carecía 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()); 
    } 
} 
+0

¿Qué funcionalidad agrega esto (que faltan las otras)? – jalanb

+1

Internamente, solo el método startSession (...) inicializará el objeto de capacidades. El objeto de capacidades es necesario para muchos métodos como takeScreenshot, executeScript y más. Pero al pasar por startSession tendrá que crear una nueva sesión de creación. Esta sobrecarga omite la creación de una nueva sesión pero todavía conduce a la inicialización de objetos de capacidades. – Yanir

3

solución Javascript:

He adjuntado correctamente a sesión actual del navegador utilizando esta función

webdriver.WebDriver.attachToSession(executor, session_id); 

documentación se puede encontrar here.

+0

Sí, ejemplo de código de trabajo de uso de la ventana abierta actualmente (que se ejecuta bajo chromedriver previamente iniciado) se puede encontrar aquí (en mi motor de prueba): https://github.com/Dzenly/tia/blob/master/api/selenium /sel-driver.js – Dzenly

1

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

sustituya el módulo de WebDriver /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py

Ej. para 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 
0

Inspirado por la respuesta de Eric, aquí está mi solución a este problema para el selenio 3.7.0. En comparación con la solución en http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/, la ventaja es que no habrá una ventana de navegador 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'] 

utilizarlo:

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)) 
0

Este fragmento de código permite volver a utilizar con éxito a instancia del navegador existente todavía evitando elevar 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/') 
Cuestiones relacionadas