send_keys - selenium webdriver python
¿Puede Selenium interactuar con una sesión de navegador existente? (11)
Es posible. Pero tienes que hackearlo un poco, hay un código. Lo que tienes que hacer es ejecutar el servidor autónomo y el "parche" 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;
}
}
}
¿Alguien sabe si Selenium (WebDriver preferiblemente) puede comunicarse y actuar a través de un navegador que ya se está ejecutando antes de iniciar un Selenium Client?
Me refiero a si Selenium es capaz de comunicarse con un navegador sin usar el Servidor Selenium (podría ser un Internet Explorer lanzado manualmente, por ejemplo).
Esta es una respuesta duplicada ** Vuelva a conectar a un controlador en python selenio ** Esto es aplicable en todos los controladores y para Java api.
abrir un controlador
driver = webdriver.Firefox() #python
extrae a session_id y _url del objeto del controlador.
url = driver.command_executor._url #"http://127.0.0.1:60622/hub" session_id = driver.session_id #''4e167f26-dc1d-4f51-a207-f761eaf73c31''
Use estos dos parámetros para conectarse a su controlador.
driver = webdriver.Remote(command_executor=url,desired_capabilities={}) driver.session_id = session_id
Y está conectado a su controlador nuevamente.
driver.get("http://www.mrsmart.in")
Esta es una solicitud de función bastante antigua: permite que el controlador de web se conecte a un navegador en ejecución . Entonces oficialmente no es compatible.
Sin embargo, hay algunos códigos de trabajo que dicen apoyar esto: https://web.archive.org/web/20171214043703/http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/ .
Este fragmento permite volver a utilizar la instancia del navegador existente sin tener que subir el navegador duplicado. Encontrado en el 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/'')
Esto es bastante fácil usando el cliente JavaScript selenium-webdriver
:
Primero, asegúrese de tener un servidor WebDriver ejecutándose. Por ejemplo, descargue ChromeDriver , luego ejecute chromedriver --port=9515
.
En segundo lugar, crea el controlador de esta manera :
var driver = new webdriver.Builder()
.withCapabilities(webdriver.Capabilities.chrome())
.usingServer(''http://localhost:9515'') // <- this
.build();
Aquí hay un ejemplo 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();
Estoy usando Rails + Cucumber + Selenium Webdriver + PhantomJS, y he estado usando una versión parcheada de Selenium Webdriver, que mantiene el navegador PhantomJS abierto entre las ejecuciones de prueba. Vea esta publicación en el blog: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/
Véase también mi respuesta a esta publicación: ¿Cómo ejecuto un comando en un navegador ya abierto desde un archivo ruby?
Inspirado por la respuesta de Eric, aquí está mi solución a este problema para el selenio 3.7.0. Comparado con la solución en http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/ , la ventaja es que no habrá una ventana en blanco cada vez que me conecte a la sesión 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 usarlo:
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))
Obtuve una solución en python, modifiqué la clase de webdriver basada en la clase PersistenBrowser que encontré.
https://github.com/axelPalmerin/personal/commit/fabddb38a39f378aa113b0cb8d33391d5f91dca5
reemplace el módulo del controlador web /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
Parece que esta característica no es oficialmente compatible con el selenio. Sin embargo, Tarun Lalwani ha creado un código Java funcional para proporcionar la función. Consulte: http://tarunlalwani.com/post/reusing-existing-browser-session-selenium-java/
Aquí está el código de muestra de trabajo, copiado del enlace de arriba:
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");
}
Su prueba debe tener un RemoteWebDriver creado a partir de una sesión de navegador existente. Para crear ese controlador, solo necesita conocer la "información de la sesión", es decir, la dirección del servidor (local en nuestro caso) donde se está ejecutando el navegador y la identificación de la sesión del navegador. Para obtener estos detalles, podemos crear una sesión de navegador con selenio, abrir la página deseada y finalmente ejecutar el script de prueba real.
No sé si hay una forma de obtener información de sesión para una sesión que no fue creada por el selenio.
Aquí hay un ejemplo de información de la sesión:
Dirección del servidor remoto: http: // localhost: 24266 . El número de puerto es diferente para cada sesión. ID de sesión: 534c7b561aacdd6dc319f60fed27d9d6.
Solución de Javascript:
Me he conectado exitosamente a una sesión de navegador existente usando esta función
webdriver.WebDriver.attachToSession(executor, session_id);
La documentación se puede encontrar here .
Todas las soluciones hasta ahora carecían de cierta funcionalidad. Aquí está mi solución:
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());
}
}