Automatizando formularios con Selenium en Python
Tags: automatizacion, selenium, python
Published: 2021-07-01 13:31:40

Las tareas repetitivas son peor de lo que pensas.

Esa tarea que haces durante 15 minutos todos los días se lleva 91.25 horas de tu año.

Los números son mucho más aterradores si aumentamos esos 15 minutos a 1 hora.

¿Cómo hacemos entonces para automatizar esas tareas triviales y recuperar nuestro tiempo?

Acá es donde entra Python al rescate.

Hoy vamos a ver cómo automatizar la web usando Python y una fantástica libreria para la automatización de navegadores llamada Selenium.

Te voy a guiar paso a paso y vamos a aprender a: 

- Configurar un entorno de automatización,
- Localizar elementos en el navegador
- Interactuar con ellos
- Y algunos casos extraños que te podes encontrar

## ⚙️ Configurar un entorno de automatización

Requerimientos:

- Tener instalado cualquier version de Python 3.X en nuestra computadora

### Driver

Lo primero que vamos a necesitar es un driver.

En este ejemplo vamos a usar chromedriver, el driver para Chrome, pero te podes descargar el driver de cualquier navegador que uses. ([Chrome](https://chromedriver.chromium.org/downloads), [Firefox](https://github.com/mozilla/geckodriver/releases/))

ℹ️ Asegurate siempre de descargar la versión del driver que soporte la versión del navegador que estás usando

Después vamos a crear la carpeta de nuestro proyecto, crear un entorno virtual e instalar Selenium.

```bash
pip install Selenium
```

Podes ir probando todo lo que vayas aprendiendo en [este formulario ficticio](https://ericluna.dev/formTest) que creé para que puedan correr sus scripts sin romper nada en ningún lado 🔨

![Formulario para testear](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ec8arr330ewvcmi50b51.png)

Para inicializar Selenium tenemos que escribir lo siguiente en nuestro script:

```python
# Importamos webdriver desde selenium
from selenium import webdriver

# Le pasamos la dirección donde descargamos nuestro driver
driver = webdriver.Chrome('/home/eric/drivers/chromedriver')

# Le pasamos la URL del sitio que vamos a automatizar
driver.get('https://ericluna.dev/formTest')
```

Si ejecutamos el programa ahora, se nos va a abrir una instancia de Chrome y va a navegar automaticamente hacia la URL que le pasamos.

## 🎯 Localizando elementos

Ahora que tenemos nuestro navegador abierto, vamos a ver como podemos seleccionar elementos del DOM para luego interactuar con ellos.

Hay muchas maneras de hacerlo, la más fácil es buscarlos por id.

```bash
# <input id="MI_ID">
driver.select_element_by_id('MI_ID')
```

Para ver el id de un elemento tenés que abrir la consola de Chrome `(Ctrl + Shift + I)` y buscar el attributo id en el campo que queremos seleccionar.

Esto no es posible siempre. A veces vamos a querer interactuar con elementos que no tienen un id.

¿Qué hacemos en esos casos?

Bueno, por suerte hay muchas formas de seleccionar un elemento.

- find_element_by_id
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector

Si no queremos andar con vueltas, la que nunca falla es Xpath.

Podés aprendar la sintaxis de cómo escribir un selector con Xpath o simplemente inspeccionar un elemento en `Chrome → Click derecho → Copiar → Copiar Xpath`.

## ⚡ Interacciones

Hasta ahora hemos logrado abrir una instancia de Chrome y seleccionar un elemento. Ahora vamos a ver como podemos interactuar con el mismo.

Vamos a poder accedder a distintas acciones dependiendo del elementos que seleccionemos.

Si seleccionamos un input de tipo texto por ejemplo, vamos a poder usar `send_keys` para pasarle el texto que queremos escribir.

```python
# <input id="nombre" type"text">
input_nombre = driver.select_element_by_id('nombre')
input_nombre.send_keys('Eric Luna')
```

En el  caso de elementos clickeables, vamos a poder usar `click` para clickearlos pero si estas interactuando con el boton de "Enviar" de un formulario deberías usar `submit`.

Basicamente, cualquier cosas que podamos hacer manualmente en el navegador, lo podemos hacer automaticamente con Selenium.

Ya sea navegar a distintas URLs, interacturar con ventanas modales, ver las cookies, arrastrar elementos, etc,etc.

## ⏱️ Tipos De Espera

Cuando cargamos una URL en el navegador de Selenium, es erroneo asumir que todo el contenido va a estar presente. Ya sea que el sitio este usando AJAX o que tu conexión a internet esté más lenta ese día, hay elementos que van a necesitar más tiempo para renderizarse antes de que estén disponibles para que los selecciones.

Por eso es que tenemos que....esperar.

Selenium nos provee dos tipos de espera. 

### Esperas Implícitas

Según la documentación: "Una espera implícita le dice al WebDriver que pida los cambios al DOM por un tiempo determinado cuando está tratando de encontrar un elemento que no está inmediatamente disponible.

```python
driver.implicitly_wait(10)
input_nombre = driver.select_element_by_id('nombre')
# Va a tirar un error si no encuentra el elemento después de 10 segundos
```

### Esperas Explícitas

Las esperas explícitas esperan a que se cumpla una cierta condición antes de continuar. De esta manera solamente esperamos el tiempo necesario, ni mas ni menos.

Podemos por ejemplo, esperar a que que el elemento sea clickeable en el DOM, o podemos esperar a que el elemento tengo un texto en particular.

Selenium viene con un montón de distintas esperas explícitas que podemos usar:

- title_is
- title_contains
- presence_of_element_located
- visibility_of_element_located
- visibility_of
- presence_of_all_elements_located
- text_to_be_present_in_element
- text_to_be_present_in_element_value
- frame_to_be_available_and_switch_to_it
- invisibility_of_element_located
- element_to_be_clickable
- staleness_of
- element_to_be_selected
- element_located_to_be_selected
- element_selection_state_to_be
- element_located_selection_state_to_be
- alert_is_present

Pero si ninguna de estas te sirven, podes implementar la tuya facilmente.

## 🔗 Links:

- 📖 [Documentación de Selenium para Python](https://selenium-python.readthedocs.io/)
- ⬇️ [Driver para Chrome](https://chromedriver.chromium.org/downloads), 
- ⬇️ [Driver para Firefox](https://github.com/mozilla/geckodriver/releases/)