Selenium, mevcut bir tarayıcı oturumuyla etkileşim kurabilir mi?


104

Selenium'un (tercihen WebDriver) bir Selenium İstemcisini başlatmadan önce çalışan bir tarayıcıyla iletişim kurabildiğini ve bununla çalışıp çalışmadığını bilen var mı?

Yani Selenium, Selenium Sunucusunu kullanmadan bir tarayıcıyla iletişim kurabilirse (örneğin, elle başlatılan bir Internet Explorer olabilir).

Yanıtlar:


35

Bu oldukça eski bir özellik isteğidir: Webdriver'ın çalışan bir tarayıcıya bağlanmasına izin verin . Yani resmi olarak desteklenmiyor.

Ancak, bunu desteklediğini iddia eden bazı çalışma kodları vardır: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/ .


Çok teşekkür ederim çünkü bu bağlantıda bunu yapmaya izin veren bir sınıf buldum, ancak maalesef bu çözümü IE ile kullanamıyorum (sadece Firefox ile). Normal bir IEDriver başlatacağım ve onunla diğer işlemlerden bir ara yazılım kullanarak iletişim kuracağım. Sınıfın neden IE üzerinde çalışmadığı konusunda bir fikriniz varsa çok sevinirim. Teşekkür ederim.
Angel Romero

Robert, şimdi 2018. Lütfen cevabınızı günceller misiniz?
MasterJoe

Herhangi birinin ihtiyacı olması durumunda, selenyumun mevcut bir tarayıcı oturumunu kullanmasını sağlamak için bazı Java kodunu denedim ve test ettim - stackoverflow.com/a/51145789/6648326 .
MasterJoe

56

Bu yinelenen bir cevaptır ** Python selenium'da bir sürücüye yeniden bağlanın ** Bu, tüm sürücüler ve java api için geçerlidir.

  1. bir sürücü aç
driver = webdriver.Firefox()  #python
  1. sürücü nesnesinden session_id ve _url'ye ayıklayın.
url = driver.command_executor._url       #"http://127.0.0.1:60622/hub"
session_id = driver.session_id            #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
  1. Sürücünüze bağlanmak için bu iki parametreyi kullanın.
driver = webdriver.Remote(command_executor=url,desired_capabilities={})
driver.close()   # this prevents the dummy browser
driver.session_id = session_id

Ve tekrar sürücünüze bağlandınız.

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

2
Tam olarak aradığım buydu. Teşekkürler.
milso

6
Her seferinde yinelenen sahte bir tarayıcı ortaya çıkması dışında benim için çalışıyor.
Pavel Vlasov

Sahte pencereyi de alıyorum, o kadar büyük bir anlaşma değil, ama hata ayıklama sırasında can sıkıcı. Nasıl kurtulacağına dair bir fikrin var mı?
Steve Gon

1
+1. 2 faktörlü kimlik doğrulama girişlerinden kaçınmak için çalışıyor, ancak yinelenen sahte tarayıcılar var. Bununla yaşayabilirim.
Sam

1
selenium.common.exceptions.SessionNotCreatedException: Message: Session is already started
Cerin

23

Bu kod parçası, mevcut tarayıcı örneğini başarıyla yeniden kullanmaya izin verirken yinelenen tarayıcıyı yükseltmekten kaçınır. Tarun Lalwani'nin blogunda bulundu .

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/')

2
Mevcut oturum kimliğini ve yürütme URL'sini otomasyon yoluyla bulmanın bir yolu var mı? Benim durumumda, başka bir uygulama bir tarayıcı oturumu açtı ve bunu kullanmak istiyorum. Bunun tarayıcı oturum kimliğini nasıl bulacağınızı önerebilir misiniz?
Sun Shine

Muhtemelen executor_command url & oturum kimliğini betik başladığında bir dosyaya dökebilir ve tarayıcı oturumunu tekrar bağlamak istediğinizde dosyadan okuyabilirsiniz.
SK Venkat

@SKVenkat chrome penceresinin oturum kimliğini nasıl alabilirim, pywinauto kullanarak açtım ve şimdi üzerinde selenuim çalıştırmak istiyorum, chrome sekmesinin oturum kimliğini almanın bir python yolu var mı
Tayyab Nasir

@TayyabNasir, lütfen yukarıdaki cevaba bakın. Yorumlanan beşinci satır, # session_id = driver.session_idpython selenium api kullanarak bir krom penceresinin oturum kimliğini almanın yoludur. Sanırım bir krom oturumundaki her sekmenin benzersiz kimliği yok.
SK Venkat

3
@SK El ile açtığım krom pencerenin oturum kimliğini istiyorum, o pencereyi selenyum kullanarak açmadım
Tayyab Nasir

12

Bu mümkün. Ama biraz hacklemelisiniz, bir kod var Yapmanız gereken tek başına sunucu çalıştırmak ve RemoteWebDriver'ı "yama" yapmaktır.

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

4
Bu mükemmel çözüme dayanarak, önceden açılmış bir Chrome tarayıcı örneğine nasıl bağlanılacağını tartıştığım eksiksiz bir blog yazısı yazdım. Tam kaynak kodu da bu blog gönderisine eklenmiştir. binaryclips.com/2015/08/25/…
katıldıaad

4

Bu özelliğin resmi olarak selenyum tarafından desteklenmediği anlaşılıyor. Ancak, Tarun Lalwani özelliği sağlamak için çalışan Java kodu oluşturdu. Bakın - http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/

Yukarıdaki bağlantıdan kopyalanan, çalışan örnek kod:

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

Testinizin mevcut bir tarayıcı oturumundan oluşturulmuş bir RemoteWebDriver'a sahip olması gerekir. Bu Sürücüyü oluşturmak için, yalnızca "oturum bilgilerini", yani tarayıcının çalıştığı sunucunun adresini (bizim durumumuzda yerel) ve tarayıcı oturum kimliğini bilmeniz gerekir. Bu ayrıntıları elde etmek için selenyum ile bir tarayıcı oturumu oluşturabilir, istenen sayfayı açabilir ve son olarak gerçek test komut dosyasını çalıştırabiliriz.

Selenium tarafından oluşturulmamış bir oturum için oturum bilgisi almanın bir yolu var mı bilmiyorum.

Aşağıda bir oturum bilgisi örneği verilmiştir:

Uzak sunucunun adresi: http: // localhost: 24266 . Her oturum için port numarası farklıdır. Oturum Kimliği: 534c7b561aacdd6dc319f60fed27d9d6.


"Selenium tarafından oluşturulmamış bir oturum için oturum bilgisi almanın bir yolu olup olmadığını bilmiyorum." aslında birkaç gündür denediğim bir sorun ... henüz başarı yok
slesh

@slesh - Bunun için yeni bir soru oluşturmanızı ve yeterince ilgi görmezse belki 100 puanınızı teklif etmenizi öneririm.
MasterJoe

Tarun Lalwani'nin çalışmalarına referans için teşekkürler. Onun sayfası ve senin cevabın arasında, anlayabildim. Bazı ifadelerin amacını açıklayan yorumların yanı sıra ithalat da güzel olurdu. Ama hepsi ve hepsi çok yardımcı oldu.
Tihamér

4

Eric'in cevabından esinlenerek, işte selenyum 3.7.0 için bu soruna çözümüm. Http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/ adresindeki çözümle karşılaştırıldığında , avantaj, mevcut oturuma her bağlandığımda boş bir tarayıcı penceresi olmayacak olmasıdır.

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

Kullanmak için:

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

Şimdiye kadarki tüm çözümlerde belirli işlevsellik yoktu. İşte benim çözümüm:

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

Bu hangi işlevselliği ekler (diğerlerinin eksik olduğu)?
jalanb

1
Dahili olarak, sadece startSession (...) yöntemi, özellikler nesnesini başlatır. Yetenekler nesnesi takeScreenshot, executeScript ve daha fazlası gibi birçok yöntem için gereklidir. Ancak startSession'dan geçerek yeni bir oturum yaratmanız gerekecek. Bu aşırı yükleme, yeni bir oturumun oluşturulmasını atlar, ancak yine de yeteneklerin nesne başlatılmasına yol açar.
Yanir

dostum, dizeleri ==
Norill Tempest

3

Javascript çözümü:

Bu işlevi kullanarak mevcut tarayıcı oturumuna başarıyla ekledim

webdriver.WebDriver.attachToSession(executor, session_id);

Belgeler burada bulunabilir .


3
Bu 4.0.0 sürümünde değil!
googamanga

1

Python'da bir çözüm buldum, bulduğum PersistenBrowser sınıfına dayalı webdriver sınıfını değiştirdim.

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

webdriver modülünü değiştirin /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py

Ej. kullanmak:

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

Rails + Cucumber + Selenium Webdriver + PhantomJS kullanıyorum ve PhantomJS tarayıcısını test çalıştırmaları arasında açık tutan Selenium Webdriver'ın maymun yamalı bir sürümünü kullanıyorum. Bu blog gönderisine bakın: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

Ayrıca bu gönderiye cevabıma da bakın: Bir Ruby dosyasından zaten açılmış olan tarayıcıda bir komutu nasıl çalıştırırım


-1

JavaScript selenium-webdriveristemcisini kullanmak oldukça kolaydır :

Öncelikle, çalışan bir WebDriver sunucunuz olduğundan emin olun. Örneğin, ChromeDriver'ı indirin , ardından çalıştırın chromedriver --port=9515.

İkincisi, sürücüyü şu şekilde oluşturun :

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

İşte eksiksiz bir örnek:

var webdriver = require ('selenyum-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();

4
MEVCUT tarayıcı oturumunu kullanmaz. Yeni bir Chromedriver oturumu oluşturur ve yeni bir tarayıcı penceresi açar. Ve getAllWindowHandles (), eski tarayıcı pencerenizin tanıtıcısını göstermeyecektir.
Dzenly

Güncelleme: Mevcut açık tarayıcı penceresine bağlanmaya izin veren seleniumhq.github.io/selenium/docs/api/javascript/module/… var.
Dzenly
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.