O Selenium pode interagir com uma session de navegador existente?

Alguém sabe se o Selenium (WebDriver de preferência) é capaz de se comunicar e agir através de um navegador que já está em execução antes de iniciar um cliente Selenium?

Quero dizer, se o Selenium é capaz de se comunicar com um navegador sem usar o Selenium Server (pode ser um Internet Explorer lançado manualmente, por exemplo).

Esta é uma solicitação de recurso bastante antiga: permitir que o webdriver seja anexado a um navegador em execução . Então, não é oficialmente suportado.

No entanto, há algum código de trabalho que afirma apoiar isso: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/ .

Esta é uma resposta duplicada ** Reconectar-se a um driver em selenium python ** Isso se aplica a todos os drivers e para java api.

  1. abrir um driver

    driver = webdriver.Firefox() #python 
  2. extraia para session_id e _url do object do driver.

     url = driver.command_executor._url #"http://127.0.0.1:60622/hub" session_id = driver.session_id #'4e167f26-dc1d-4f51-a207-f761eaf73c31' 
  3. Use esses dois parâmetros para se conectar ao seu driver.

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

    E você está conectado ao seu driver novamente.

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

É possível. Mas você tem que hackear um pouco, existe um código O que você tem a fazer é rodar um servidor independente e “patch” 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; } } } 

Esse snippet permite reutilizar a instância do navegador existente, evitando, ainda, aumentar o navegador duplicado. Encontrado no 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 as soluções até agora faltavam certas funcionalidades. Aqui está a minha solução:

 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()); } } 

Solução de Javascript:

Eu tenho anexado com sucesso a session do navegador existente usando esta function

 webdriver.WebDriver.attachToSession(executor, session_id); 

A documentação pode ser encontrada aqui .

Eu tenho uma solução em python, eu modifiquei a class webdriver bassed na class PersistenBrowser que eu encontrei.

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

substitua o módulo do webdriver /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 

Estou usando o Rails + Cucumber + Selenium Webdriver + PhantomJS, e tenho usado uma versão com correção de macacos do Selenium Webdriver, que mantém o navegador PhantomJS aberto entre execuções de teste. Veja este post: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-entre-estudos/

Veja também a minha resposta para este post: Como faço para executar um comando no navegador já aberto a partir de um arquivo ruby

Isso é muito fácil usando o cliente JavaScript selenium-webdriver :

Primeiro, verifique se você tem um servidor WebDriver em execução. Por exemplo, faça o download do ChromeDriver e execute chromedriver --port=9515 .

Em segundo lugar, crie o driver assim :

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

Aqui está um exemplo 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 pela resposta de Eric, aqui está a minha solução para este problema para o selenium 3.7.0. Comparado com a solução em http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/ , a vantagem é que não haverá uma janela do navegador em branco toda vez que eu me conectar à session 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 usá-lo:

 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 esse recurso não é oficialmente suportado pelo selenium. Mas Tarun Lalwani criou o código Java para fornecer o recurso. Consulte – http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/

Aqui está o código de exemplo de trabalho, copiado do link acima:

 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"); } 

Seu teste precisa ter um RemoteWebDriver criado a partir de uma session de navegador existente. Para criar esse Driver, você só precisa saber as “informações da session”, ou seja, o endereço do servidor (local no nosso caso) onde o navegador está em execução e o ID da session do navegador. Para obter esses detalhes, podemos criar uma session do navegador com selenium, abrir a página desejada e, finalmente, executar o script de teste real.

Não sei se existe uma maneira de obter informações da session para uma session que não foi criada por selenium.

Aqui está um exemplo de informação da session:

Endereço do servidor remoto: http: // localhost: 24266 . O número da porta é diferente para cada session. Id da session: 534c7b561aacdd6dc319f60fed27d9d6.

    Intereting Posts