Python + Selenium webdriver: utilizando el método de autenticación

Estoy utilizando Python + selenium webdriver para automatizar cheques. Estoy atascado en sitios web que solicitan autenticación http a través de una ventana emergente.

Estoy tratando de usar el método de “autenticación” a través del siguiente código:

#init. driver = webdriver.Firefox() driver.get(url) #get to the auth popup window by clicking relevant link elem = driver.find_element_by_id("login_link") elem.click() #use authenticate alert method driver._switch_to.alert.authenticate("login", "password") 

La información / doc (escasa) relacionada con este método indica que debe enviar las credenciales proporcionadas y validar la autenticación http. No lo hace y estoy recibiendo el siguiente error:

Archivo “/usr/local/lib/python2.7/dist-packages/selenium/webdriver/common/alert.py”, línea 105, en authenticate self.driver.execute (Command.SET_ALERT_CREDENTIALS, {‘username’: username, ‘contraseña’: contraseña}) Archivo “/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py”, línea 201, en ejecutar self.error_handler.check_response (respuesta) Archivo ” /usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py “, línea 159, en check_response raise exception_class (value) selenium.common.exceptions.WebDriverException: Mensaje: Comando no reconocido: POST / session / c30d03e1-3835-42f5-ace0-968aef486b36 / alert / credentials

¿hay algo que me esté perdiendo aquí? ¿Alguien ha encontrado el mismo problema y lo ha resuelto?

PD: el truco de http: // nombre de usuario: contraseña @ url no funciona para mí en mis condiciones de prueba.

Es bastante fácil trabajar con la autenticación básica para realizar pruebas automatizadas, sin tener que lidiar con alertas / diálogos nativos u otras diferencias de navegador.

El enfoque que he utilizado con mucho éxito en el mundo Java es configurar un servidor proxy Browsermob en código y registrar un RequestInterceptor para interceptar todas las solicitudes entrantes (que coinciden con el patrón de host / URL en cuestión). Cuando tenga una solicitud que de lo contrario necesitaría una autenticación Básica, agregue un encabezado HTTP de Authorization con las credenciales requeridas (‘Básico’ + la cadena de usuario: pase ‘Codificada en Base64. Por lo tanto, para’ foo: barra ‘debe establecer el valor Basic Zm9vOmJhcg== )

Inicie el servidor, configúrelo como un proxy web para el tráfico de Selenium y, cuando se realice una solicitud que requiera autenticación, el proxy agregará el encabezado, el navegador lo verá, verificará las credenciales y no necesitará abrir el cuadro de diálogo.

Aunque la técnica puede parecer laboriosa, al tener el encabezado configurado automáticamente para cada solicitud, no tiene que agregar explícitamente user:pass@ a cualquier URL que pueda necesitarla, donde existen varias formas de ingresar al área de autenticación. Además, a diferencia de user:pass@ users, no tiene que preocuparse por el almacenamiento en caché del navegador (o dejar de almacenar en caché, después de un cierto tiempo) el encabezado, o sobre el cruce de HTTP / HTTPS.

Esa técnica funciona muy bien, pero ¿cómo lograr esto en Python?

Podría usar este contenedor de Python para Browsermob , que expone su API REST en Python. Esta es la llamada REST que necesitarás:

POST / proxy / [puerto] / headers – Establece y anula los encabezados de solicitud HTTP. Por ejemplo, configurar un User-Agent personalizado. Los datos de carga útil deben ser un conjunto de encabezados codificados en json (no codificados en url)

Entonces, del ejemplo anterior (pseudocódigo):

 POST localhost:8787/proxy//headers '{"Authorization": "Basic Zm9vOmJhcg=="}' 

Alternativamente, podría ver esta respuesta para un servidor proxy Python personalizado utilizando Twisted.

La autenticación básica es posible en la URL, pero tendrá que establecer una preferencia:

 from selenium import webdriver profile = webdriver.FirefoxProfile() profile.set_preference("network.http.phishy-userpass-length", 255) driver = webdriver.Firefox(profile) driver.get("http://admin:admin@the-internet.herokuapp.com/basic_auth") 

Si no funciona en su caso, entonces no es autenticación básica.