webentwicklung-frage-antwort-db.com.de

Kann Selen mit einer vorhandenen Browsersitzung interagieren?

Weiß jemand, ob Selenium (vorzugsweise WebDriver) in der Lage ist, mit einem bereits laufenden Browser zu kommunizieren und über diesen zu agieren, bevor ein Selenium-Client gestartet wird?

Ich meine, wenn Selenium in der Lage ist, mit einem Browser zu kommunizieren, ohne den Selenium-Server zu verwenden (mit könnte beispielsweise ein Internet Explorer manuell gestartet werden).

58
Angel Romero

Dies ist eine ziemlich alte Feature-Anfrage: Erlaube Webdriver, sich an einen laufenden Browser anzuschließen . Es wird also offiziell nicht unterstützt.

Es gibt jedoch einige Arbeitscodes, die dies unterstützen sollen: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-Selenium -Java / .

24
Robert Munteanu

Dies ist eine doppelte Antwort. ** Verbinde dich erneut mit einem Treiber in python Selenium ** Dies gilt für alle Treiber und für Java api.

  1. öffne einen Fahrer

    driver = webdriver.Firefox()  #python
    
  2. entpacken nach Session_ID und _URL aus dem Treiberobjekt.

    url = driver.command_executor._url       #"http://127.0.0.1:60622/hub"
    session_id = driver.session_id            #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
    
  3. Verwenden Sie diese beiden Parameter, um eine Verbindung zu Ihrem Treiber herzustellen.

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

    Und Sie sind wieder mit Ihrem Fahrer verbunden.

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

Mit diesem Snippet können vorhandene Browserinstanzen erfolgreich wiederverwendet werden, ohne dass der doppelte Browser ausgelöst wird. Gefunden bei Tarun Lalwani 's Blog.

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/')
14
Pavel Vlasov

Es ist möglich. Aber Sie müssen es ein wenig hacken, es gibt einen Code. Sie müssen nur einen eigenständigen Server ausführen und RemoteWebDriver "patchen"

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
Alex Ilyin

Allen Lösungen fehlte bisher eine bestimmte Funktionalität. Hier ist meine Lösung:

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
Yanir

Javascript Lösung:

Ich habe mit dieser Funktion erfolgreich eine Verbindung zu einer vorhandenen Browsersitzung hergestellt

webdriver.WebDriver.attachToSession(executor, session_id);

Dokumentation finden Sie hier .

3
gm2008

Inspiriert von Erics Antwort, hier ist meine Lösung für dieses Problem für Selen 3.7.0. Gegenüber der Lösung unter http://tarunlalwani.com/post/reusing-existing-browser-session-Selenium/ ist der Vorteil, dass bei jeder Verbindung kein leeres Browserfenster angezeigt wird auf die bestehende Sitzung.

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

Um es zu benutzen:

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))
3
Nan Zhong

Ich habe eine Lösung in Python gefunden. Ich habe die Webdriver-Klasse geändert, die in der PersistenBrowser-Klasse enthalten ist, die ich gefunden habe.

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

ersetzen Sie das Webdriver-Modul /usr/local/lib/python2.7/dist-packages/Selenium/webdriver/remote/webdriver.py

Ej. benutzen:

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
Eric Axel

Es scheint, dass diese Funktion von Selen nicht offiziell unterstützt wird. Tarun Lalwani hat jedoch Arbeitscode Java erstellt, um die Funktion bereitzustellen. Siehe - http://tarunlalwani.com/post/reusing-existing-browser-session-Selenium-Java/

Hier ist der funktionierende Beispielcode, der vom obigen Link kopiert wurde:

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

Für Ihren Test muss ein RemoteWebDriver aus einer vorhandenen Browsersitzung erstellt werden. Um diesen Treiber zu erstellen, müssen Sie nur die "Sitzungsinformationen" kennen, d. H. Die Adresse des Servers (in unserem Fall lokal), auf dem der Browser ausgeführt wird, und die Browsersitzungs-ID. Um diese Details zu erhalten, können wir eine Browsersitzung mit Selenium erstellen, die gewünschte Seite öffnen und dann das eigentliche Testskript ausführen.

Ich weiß nicht, ob es eine Möglichkeit gibt, Sitzungsinformationen für eine Sitzung abzurufen, die nicht von Selen erstellt wurde.

Hier ist ein Beispiel für Sitzungsinformationen:

Adresse des Remote-Servers: http: // localhost: 24266 . Die Portnummer ist für jede Sitzung unterschiedlich. Sitzungs-ID: 534c7b561aacdd6dc319f60fed27d9d6.

1
MasterJoe2

Ich verwende Rails + Cucumber + Selenium Webdriver + PhantomJS und ich verwende eine von Affen gepatchte Version von Selenium Webdriver, die den PhantomJS-Browser zwischen Testläufen geöffnet hält. Siehe diesen Blog-Beitrag : http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

Siehe auch meine Antwort auf diesen Beitrag: Wie führe ich einen Befehl in einem bereits geöffneten Browser aus einer Ruby Datei

0
rap1ds

Dies ist mit dem JavaScript-Client Selenium-webdriver Ziemlich einfach:

Stellen Sie zunächst sicher, dass ein WebDriver-Server ausgeführt wird. Beispiel: ChromeDriver herunterladen , dann chromedriver --port=9515 Ausführen.

Zweitens erstellen Sie den Treiber wie folgt :

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

Hier ist ein vollständiges Beispiel:

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();
0
Dan Dascalescu