¿Cómo puedo volver a conectarme al navegador abierto por webdriver con selenium?
Por razones desconocidas, mi navegador abre las páginas de prueba de mi servidor remoto muy lentamente. Entonces, estoy pensando que si puedo volver a conectarme al navegador después de salir del script pero no lo ejecuto, webdriver.quit()
esto dejará el navegador abierto. Probablemente sea una especie de GANCHO o identificador de controlador web. Busqué el documento API de selenio pero no encontré ninguna función. Estoy usando Chrome 62,x64,windows 7,selenium 3.8.0. Apreciaré mucho si la pregunta se puede resolver o no.
No , no puede volver a conectarse a la sesión de navegación web anterior después de salir del script. Incluso si puede extraer el Session ID
y Cookies
otros atributos de sesión del contexto de navegación anterior , no podrá pasar esos atributos como HOOK al WebDriver .
Una forma más limpia sería llamar webdriver.quit()
y luego abarcar un nuevo contexto de navegación .
Bucear profundo
Ha habido muchas discusiones e intentos de volver a conectar WebDriver a un contexto de navegación existente . En la discusión Permitir que el controlador web se adjunte a un navegador en ejecución, Simon Stewart [Creator WebDriver] mencionó claramente:
- Volver a conectarse a un contexto de navegación existente es una característica específica del navegador y, por lo tanto, no se puede implementar de forma genérica.
- Conexplorador de Internet, es posible iterar sobre las ventanas abiertas en el sistema operativo y encontrar el proceso de IE correcto al que adjuntar.
- firefoxyGoogle Chromedebe iniciarse en un modo y configuración específicos, lo que efectivamente significa que simplemente conectarse a una instancia en ejecución no es técnicamente posible.
tl; dr.
webdriver.firefox.useExistente no implementado
Sí , en realidad eso es bastante fácil de hacer.
Una sesión de Selenium <-> webdriver está representada por una URL de conexión y session_id, simplemente se vuelve a conectar a una existente.
Descargo de responsabilidad : el enfoque utiliza propiedades internas del selenio ("privadas", en cierto modo), que pueden cambiar en nuevas versiones; será mejor que no lo uses para código de producción; es mejor no usarlo contra SE remoto (su centro o proveedor como BrowserStack/Sauce Labs), debido a una advertencia/drenaje de recursos que se explica al final.
Cuando se inicia una instancia de webdriver, necesita obtener las propiedades mencionadas anteriormente; muestra:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.google.com/')
# now Google is opened, the browser is fully functional; print the two properties
# command_executor._url (it's "private", not for a direct usage), and session_id
print(f'driver.command_executor._url: {driver.command_executor._url}')
print(f'driver.session_id: {driver.session_id}')
Una vez conocidas esas dos propiedades, se puede conectar otra instancia; el "truco" consiste en iniciar un Remote
controlador y proporcionar lo _url
anterior; así se conectará al proceso de selenio en ejecución:
driver2 = webdriver.Remote(command_executor=the_known_url)
# when the started selenium is a local one, the url is in the form 'http://127.0.0.1:62526'
Cuando se ejecute, verá que se abre una nueva ventana del navegador.
Esto se debe a que al iniciar el controlador, la biblioteca de Selenium inicia automáticamente una nueva sesión y ahora tiene 1 proceso de controlador web con 2 sesiones (instancias de navegador).
Si navega a una URL, verá que se ejecuta en esa nueva instancia del navegador, no en la que quedó del inicio anterior, lo cual no es el comportamiento deseado.
En este punto, se deben hacer dos cosas: a) cerrar la sesión SE actual ("la nueva") y b) cambiar esta instancia a la sesión anterior:
if driver2.session_id != the_known_session_id: # this is pretty much guaranteed to be the case
driver2.close() # this closes the session's window - it is currently the only one, thus the session itself will be auto-killed, yet:
driver2.quit() # for remote connections (like ours), this deletes the session, but does not stop the SE server
# take the session that's already running
driver2.session_id = the_known_session_id
# do something with the now hijacked session:
driver.get('https://www.bing.com/')
Y eso es todo: ahora está conectado a la sesión anterior/ya existente, con todas sus propiedades (cookies, LocalStorage, etc.).
Por cierto, no es necesario que los proporcione desired_capabilities
al iniciar el nuevo controlador remoto; estos se almacenan y se heredan de la sesión existente que asumió.
Advertencia : tener un proceso SE en ejecución puede provocar una fuga de recursos en el sistema.
Siempre que uno se inicia y luego no se cierra, como en la primera parte del código, permanecerá allí hasta que lo elimine manualmente. Con esto quiero decir que, en Windows, por ejemplo, verás un proceso "chromedriver.exe", que tendrás que finalizar manualmente una vez que hayas terminado. No puede ser cerrado por un controlador que se haya conectado a él como a un proceso de selenio remoto.
La razón: cada vez que inicia una instancia de navegador local y luego llama a su quit()
método, tiene 2 partes: la primera es eliminar la sesión de la instancia de Selenium (lo que se hace en el segundo fragmento de código), y la La otra es detener el servicio local (Chrome/geckodriver), que generalmente funciona bien.
La cuestión es que, para las sesiones remotas, falta la segunda pieza: su máquina local no puede controlar un proceso remoto, ese es el trabajo del concentrador de ese control remoto. Entonces esa segunda parte es literalmente una pass
declaración de Python: una operación no operativa.
Si inicia demasiados servicios de Selenium en un centro remoto y no tiene control sobre él, se producirá un drenaje de recursos de ese servidor. Los proveedores de la nube como BrowserStack toman medidas contra esto: están cerrando servicios sin actividad durante los últimos 60 años, etc., pero esto es algo que usted no desea hacer.
Y en cuanto a los servicios SE locales, no olvide limpiar ocasionalmente el sistema operativo de los controladores de Selenium huérfanos que olvidó :)
Bien, después de mezclar varias soluciones compartidas aquí y modificarlas, ahora tengo esto funcionando como se muestra a continuación. El script utilizará la ventana de Chrome abierta previamente, si está presente; la conexión remota es perfectamente capaz de cerrar el navegador si es necesario y el código funciona bien.
Me encantaría encontrar una forma de automatizar la obtención de session_id y la URL de la sesión activa anterior sin tener que escribirlos en un archivo durante la sesión anterior para recogerlos...
Esta es mi primera publicación aquí, así que me disculpo por romper las normas.
#Set manually - read/write from a file for automation
session_id = "e0137cd71ab49b111f0151c756625d31"
executor_url = "http://localhost:50491"
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
remote_session = 0
#Try to connect to the last opened session - if failing open new window
try:
driver = attach_to_session(executor_url,session_id)
driver.current_url
print(" Driver has an active window we have connected to it and running here now : ")
print(" Chrome session ID ",session_id)
print(" executor_url",executor_url)
except:
print("No Driver window open - make a new one")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=myoptions)
session_id = driver.session_id
executor_url = driver.command_executor._url
para Chromium puede obtener una lista de los procesos en ejecución del navegador, inspeccionar la línea de comandos de este proceso y buscar "--remote-debugging-port=", extraer ese número de puerto y usarlo en la inicialización del controlador web.
establezca las Opciones del controlador en
ChromiumOptions.DebuggerAddress = "127.0.0.1:" & remotePort
sin ninguna otra opción configurada iniciar
driver As IWebDriver = New EdgeDriver(driverService, ChromiumOptions, CommandTimeout)
Esa es la parte de VB.net que me funciona, pero creo que es posible traducirla y usarla en otros idiomas también.
y utilice el controlador como de costumbre. puede continuar en el punto donde la página se dejó abierta, o crear una ventana conocida y cerrar la anterior si desea comenzar de nuevo, pero con las cookies y el caché anteriores.
es posible que desee eliminar los procesos antiguos "webdriver.exe", porque en cada reconexión generará uno conocido.
de esta manera simulas el comportamiento real del usuario porque los usuarios normales no siempre navegan en privado. Regresaron a su sitio con cookies antiguas y datos en caché. para que pueda optimizar su sitio para manejar adecuadamente los activos almacenados en caché antiguos y encontrar formas en las que el usuario no necesite forzar la recarga del sitio o limpiar el caché cada vez que el sitio recibe una actualización.