Peut Sélénium interagir avec une session de navigateur?

est-ce que quelqu'un sait si Selenium (WebDriver de préférence) est capable de communiquer et d'agir avec un navigateur qui fonctionne déjà avant de lancer un Client Selenium?

je veux dire si Selenium est capable de communiquer avec un navigateur sans utiliser le serveur Selenium (Avec pourrait être un Internet Explorer lancé manuellement par exemple).

41
demandé sur Tomasz Stanczak 2011-12-01 20:29:51

11 réponses

il s'agit d'une requête assez ancienne: permet à webdriver de se connecter à un navigateur en cours d'exécution . Donc il n'est pas officiellement soutenu.

cependant, il y a un code de travail qui prétend soutenir ceci: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java / .

19
répondu Robert Munteanu 2018-07-06 12:44:29

c'est une réponse en double ** Reconnecter à un pilote dans Python selenium * * ceci est applicable à tous les pilotes et pour l'api java.

  1. ouvrir un conducteur

    driver = webdriver.Firefox()  #python
    
  2. extrait de session_id et _url à partir du pilote de l'objet.

    url = driver.command_executor._url       #"http://127.0.0.1:60622/hub"
    session_id = driver.session_id            #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
    
  3. utilisez ces deux paramètres pour vous connecter à votre pilote.

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

    et vous êtes connecté à votre pilote.

    driver.get("http://www.mrsmart.in")
    
20
répondu Manoj Sahu 2018-08-24 12:21:43

c'est possible. Mais vous devez le modifier un peu, il y a un code Ce que vous devez faire est d'exécuter stand alone server et "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<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;
        }
    }
}
9
répondu Alex Ilyin 2012-04-26 09:42:49

cet extrait permet avec succès de réutiliser l'instance de navigateur existante tout en évitant d'élever le navigateur dupliqué. Trouvé sur le 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/')
4
répondu Pavel Vlasov 2018-09-26 16:20:10

toutes les solutions jusqu'à présent manquaient d'une certaine fonctionnalité. Voici ma solution:

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());
    }
}
3
répondu Yanir 2016-08-08 11:21:41

solution Javascript:

j'ai attaché avec succès à la session de navigateur existante en utilisant cette fonction""

webdriver.WebDriver.attachToSession(executor, session_id);

Documentation peut être trouvé ici .

3
répondu gm2008 2017-02-14 12:10:53

c'est assez facile en utilisant le JavaScript selenium-webdriver client:

tout d'abord, assurez-vous que vous avez un serveur WebDriver en cours d'exécution. Par exemple, télécharger ChromeDriver , puis exécuter chromedriver --port=9515 .

Deuxièmement, créer le pilote comme ceci :

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

voici un exemple complet:

var webdriver = require('sélénium 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();
1
répondu Dan Dascalescu 2015-08-06 04:02:01

j'ai eu une solution en python, j'ai modifié la classe webdriver basée sur la classe PersistenBrowser que j'ai trouvé.

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

remplacer le module webdriver /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py

Ej. a utiliser:

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
1
répondu Eric Axel 2017-03-23 23:06:09

J'utilise Rails + Cucumber + Selenium Webdriver + PhantomJS, et j'ai utilisé une version patchée de Selenium Webdriver, qui maintient le navigateur de PhantomJS ouvert entre les essais. Voir ce billet de blog: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

voir aussi ma réponse à ce post: Comment puis-je exécuter une commande sur un navigateur déjà ouvert à partir d'un fichier ruby

0
répondu rap1ds 2017-05-23 12:18:14

il semble que cette caractéristique ne soit pas officiellement soutenue par le sélénium. Mais, Tarun Lalwani a créé le code Java de travail pour fournir la fonctionnalité. Se référer à http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/

voici le code de l'échantillon de travail, copié à partir du lien ci-dessus:

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

votre test doit avoir un driver Remoteweb créé à partir d'une session de navigateur existante. Pour créer ce Pilote, vous n'avez besoin de connaître que les "informations de session", c'est-à-dire l'adresse du serveur (local dans notre cas) où le navigateur est en cours d'exécution et l'id de session du navigateur. Pour obtenir ces détails, nous pouvons créer une session de navigateur avec selenium, ouvrir la page désirée, puis finalement exécuter le script de test réel.

Je ne sais pas s'il y a un moyen d'obtenir des informations de session pour une session qui n'a pas été créée par le sélénium.

voici un exemple de session info:

adresse du serveur distant: http://localhost:24266 . Le numéro de port est différent pour chaque session. Numéro de Session : 534c7b561aacdd6dc319f60fed27d9d6.

0
répondu testerjoe2 2018-07-03 02:36:30

inspirée de la réponse D'Eric, voici ma solution à ce problème pour le sélénium 3.7.0. Par rapport à la solution de http://tarunlalwani.com/post/reusing-existing-browser-session-selenium / , l'avantage est qu'il n'y aura pas de fenêtre de navigateur vide chaque fois que je me connecte à la session existante.

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']

pour l'utiliser:

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
répondu Nan Zhong 2018-09-26 16:22:53