2011-12-01 108 views
26

有誰知道Selenium(WebDriver最好)是否能夠在啓動Selenium客戶端之前通過已經運行的瀏覽器進行通信並執行操作?Selenium可以與現有瀏覽器會話進行交互嗎?

我的意思是如果Selenium能夠在不使用Selenium服務器的情況下與瀏覽器通信(例如可以是手動啓動的Internet Explorer)。

回答

16

這是一個很舊的功能請求:Allow webdriver to attach to a running browser。所以現在不可能。

+0

非常感謝你,因爲在那個鏈接中我找到了一個允許這樣做的類,但是不幸的是我不能在IE中使用這個解決方案(只適用於Firefox)。我將啓動一個普通的IEDriver,並使用中間件從其他進程中與其交流。如果你有一個想法,爲什麼課程不在IE上工作,我將不勝感激。謝謝。 –

8

這是可能的。但是,你必須搞出了一點,有一個代碼 你所要做的就是運行獨立的服務器和「補丁」 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

基於這個出色的解決方案,我寫了一篇完整的博客文章,其中我已經討論瞭如何連接到一個已經打開的Chrome瀏覽器實例。完整的源代碼也附在該博客文章上。 http://binaryclips.com/2015/08/25/selenium-webdriver-in-c-how-to-use-the-existing-window-of-chrome-browser/ – joinsaad

0

我使用Rails +黃瓜+硒的webdriver + PhantomJS,而且我一直使用Selenium Webdriver的猴子補丁版本,它可以在測試運行之間保持PhantomJS瀏覽器的打開狀態。看到這個博客帖子:http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

另見我回答這個帖子:How do I execute a command on already opened browser from a ruby file

+0

感謝您的回答 –

+0

如果有人要去要至少回答一個答案,他們應該解釋爲什麼他們這樣做 – BringBackCommodore64

0

這是很容易使用JavaScript selenium-webdriver客戶端:

首先,確保你有一個webdriver的服務器上運行。例如,download ChromeDriver,然後運行chromedriver --port=9515

其次,創建驅動程序like this

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

這裏有一個完整的例子:

VAR的webdriver =需要( '硒的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

它不使用EXISTING瀏覽器會話。它創建一個新的chromedriver會話並打開一個新的瀏覽器窗口。而getAllWindowHandles()將不會顯示您的舊瀏覽器窗口的句柄。 – Dzenly

+0

更新:有 http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebDriver.html#WebDriver.attachToSession 它允許連接到現有的打開的瀏覽器窗口。 – Dzenly

16

這是一個重複的答案 **重新在Python硒司機**這是適用於所有驅動程序和Java API的。

  1. 打開駕駛員

    driver = webdriver.Firefox() #python 
    
  2. 提取物以SESSION_ID和_url來自驅動器的對象。

    url = driver.command_executor._url  #"http://127.0.0.1:60622/hub" 
    session_id = driver.session_id   #'4e167f26-dc1d-4f51-a207-f761eaf73c31' 
    
  3. 使用這兩個參數連接到您的驅動程序。

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

    然後您又連接到您的驅動程序。

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

這正是我正在尋找的。謝謝。 – milso

+2

似乎不再工作。 – Sajuuk

+0

它適用於我,除了重複的虛擬瀏覽器每次都在提高。 –

2

所有的解決方案至今都缺乏的某些功能。 這裏是我的解決方案:

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

添加了哪些功能(其他人缺失)? – jalanb

+1

在內部,只有startSession(...)方法將初始化功能對象。 許多方法(如takeScreenshot,executeScript等)都需要capabilities對象。 但是通過檢查startSession,你將不得不創建一個新的會話創建。 此重載會跳過新會話的創建,但仍會導致對象初始化功能。 – Yanir

3

JavaScript解決方案:

使用此功能

webdriver.WebDriver.attachToSession(executor, session_id); 

文檔可以發現here我已經成功地連接到現有的瀏覽器會話。

+0

是的,使用當前打開的窗口(在以前啓動的chromedriver下運行)的工作代碼示例可以在這裏找到(在我的測試引擎中): https://github.com/Dzenly/tia/blob/master/api/selenium /sel-driver.js – Dzenly

1

我在python中得到了一個解決方案,我修改了我發現的基於PersistenBrowser類的webdriver類。

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

取代的webdriver模塊/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py

EJ。使用:

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

受Eric的回答啓發,這裏是我對selenium 3.7.0的這個問題的解決方案。與http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/的解決方案相比,優點是每次連接到現有會話時都不會有空白的瀏覽器窗口。

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

要使用它:

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

這個片段成功地允許重新使用現有的瀏覽器實例但避免提高重複瀏覽器。發現在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/') 
相關問題