Selenium en Github Actions para Web Scraping

Selenium Web Scraping Github Actions

Como ejecutar un trabajo con Selenium desde Github Actions utilizando Docker.

Maxi Galoto
2024-03-20

react

Inicio



Introducción

Volver al Inicio



En el desarrollo y la extracción de datos web, muchas veces nos enfrentamos a desafíos al intentar obtener información de páginas web dinámicas. Estas páginas utilizan técnicas como AJAX, JavaScript y actualizaciones en tiempo real para mostrar contenido, lo que dificulta la extracción directa mediante librerías tradicionales para Web Scraping.

En este tutorial, exploraremos cómo podemos utilizar Selenium junto con Python dentro de un contenedor Docker en GitHub Actions para preparar un entorno útil de Web Scraping en paginas dinámicas dentro de un servidor en Github Actions. Selenium nos permite simular acciones de usuario, como hacer clic en botones, llenar formularios y navegar por el contenido que se carga dinámicamente, lo cual es crucial para obtener información que no está disponible en el HTML estático inicial de la página.

Las páginas dinámicas requieren ejecución de JavaScript en el navegador del cliente para actualizar su contenido, lo que significa que la estructura y los datos de la página pueden cambiar según las interacciones del usuario o eventos externos. Esto presenta un desafío significativo para las técnicas de scraping tradicionales y resalta la utilidad de Selenium para acceder y extraer datos de manera efectiva en entornos web modernos.

Ahora que entendemos la utilidad de Selenium para extraer datos de paginas web vamos a pasar a explicar el paso a paso para poder automatizar un Script de Web Scraping en Github Actions con Selenium,



Desarrollo

Volver al Inicio



Construcción de la Imagen:

Se utiliza Chromium como navegador para utilizar Selenium.

# Este comando indica que la imagen base para este contenedor será Python 3.9.6. 
# La imagen base proporciona el entorno inicial sobre el cual se construirá
FROM python:3.9.6

# Establece el directorio de trabajo dentro del contenedor en /app. 
# Todas las instrucciones siguientes se ejecutarán en este directorio
# a menos que se especifique lo contrario.
WORKDIR /app


# Estas líneas de comandos se encargan de instalar Chromium en el contenedor
RUN apt-get update && \
    apt-get install chromium -y && \
    apt-get clean

# Copia el archivo requirements.txt desde el directorio raíz del 
# contexto de construcción de Docker (donde está tu # Dockerfile) 
# al directorio /app dentro del contenedor.
COPY /requirements.txt .

# Instala las dependencias especificadas en requirements.txt usando pip.
RUN pip install --no-cache-dir -r requirements.txt

# Copia todos los archivos y directorios desde el contexto 
# de construcción de Docker (donde está el Dockerfile) al 
# directorio /app dentro del contenedor.
COPY . .

requirements.txt.

Como minimo necesitan las siguientes librerías:

selenium==4.18.1

(Permite interactuar con páginas web de manera programática, realizando acciones como hacer clic en botones, enviar formularios, extraer datos y más.)

webdriver-manager==4.0.1

(WebDriver Manager es una biblioteca que simplifica el manejo de los controladores necesarios para interactuar con diferentes navegadores a través de Selenium.)

Imagen.

El primer comando a utilizar para crear la imagen es el siguiente:

nombre_de_usuario: Nuestro nombre de usuario de DockerHub

nombre_de_repositorio: Nombre del repositorio al cual queremos subir la imagen

tag: Tag de la imagen.


docker build -t nombre_de_usuario/nombre_de_repositorio:tag .

Luego, despues de logearse en DockerHub, subimos la imagen:


docker push  -t nombre_de_usuario/nombre_de_repositorio:tag .

Archivo YAML Github Actions.

Para poder correr un Script desde Github Actions de forma automatica cuando ocurra un evento o un schedule programado necesitamos utilizar un archivo YAML que se encuentre dentro de nuestro repositorio en la siguiente ruta: /.github/workflows/

Un ejemplo puede ser el siguiente:

Cuando se registren cambios en la rama main que se ejecute un Github Actions en una VM Ubuntu utilizando la imagen que creamos en el paso anterior corriendo el script main.py.


name: selenium_actions
on: 
  push:
    branches: [main]
jobs:
  scrape:
    runs-on: ubuntu-latest
    container: 
      image: nombre_de_usuario/nombre_de_repositorio:tag
    steps:
    - name: checkout_repo
      uses: actions/checkout@v3
      with: 
        ref: 'main'
    - name: Run script
      run: python main.py

Script Python:

Para instanciar el WebDriver se utiliza la siguiente función con estas características:

ChromeDriverManager para manejar la descarga e instalación del ChromeDriver específico para Chromium. Esto asegura que siempre estés utilizando una versión compatible y actualizada del driver.

Options es un objeto para almacenar las opciones de configuración del navegador.

Una lista de opciones (options) se define con configuraciones específicas como:

–headless: Ejecutar el navegador en modo sin cabeza (sin interfaz gráfica).

–disable-gpu: Deshabilitar el uso de la GPU, útil en entornos headless.

–window-size=1920,1200: Establecer el tamaño de la ventana del navegador.

–ignore-certificate-errors: Ignorar errores de certificado SSL.

–disable-extensions: Deshabilitar las extensiones del navegador.

–no-sandbox: Ejecutar Chrome en modo sin sandbox (seguridad reducida).

–disable-dev-shm-usage: Deshabilitar el uso de /dev/shm para mejorar la compatibilidad en entornos Docker.

Service se utiliza para gestionar el servicio del ChromeDriver, que es un ejecutable necesario para comunicarse con el navegador Chrome o Chromium desde Selenium.


def getDriver(self):
    chrome_service = Service(ChromeDriverManager(chrome_type=ChromeType.CHROMIUM).install())

    chrome_options = Options()
    options = [
        "--headless",
        "--disable-gpu",
        "--window-size=1920,1200",
        "--ignore-certificate-errors",
        "--disable-extensions",
        "--no-sandbox",
        "--disable-dev-shm-usage"
    ]
    for option in options:
        chrome_options.add_argument(option)

    driver = webdriver.Chrome(service=chrome_service, options=chrome_options)
    return driver

Uso del driver en el Script:


driver = getDriver()

Cierre del driver una vez terminado el scraping:


driver.quit()



Conclusión

Volver al Inicio



En este post, hemos explorado cómo utilizar una imagen Docker con Selenium y Python en GitHub Actions para interactuar con páginas web dinámicas y asi poder automatizar un Script.

Utilizando herramientas como selenium y webdriver-manager, se configuro un entorno sencillo de desarrollo que facilita la automatización de tareas, como la simulación de interacciones de usuario y la extracción de datos actualizados en tiempo real. Además, se aprovechado las ventajas de Docker para asegurar un entorno de desarrollo consistente y reproducible, fundamental para la integración continua con GitHub Actions.

En el mundo del Web Scraping no hay limites a la hora de desarrollar Scripts para automatizar la extracción de datos de temas de nuestro interés!