Volver al blog
Guías
Mihai MaximLast updated on Mar 31, 20265 min read

Cómo ejecutar JavaScript con Scrapy

Cómo ejecutar JavaScript con Scrapy

Introducción

¡Bienvenido al apasionante mundo del scraping de sitios web dinámicos! Como ya sabrás por nuestros artículos anteriores, este tipo de sitios web pueden resultar un poco complicados de explorar con las herramientas tradicionales de scraping. ¡Pero no te preocupes! Scrapy, tu fiel asistente de scraping, te echa una mano con una gran variedad de plugins y bibliotecas que hacen que el scraping de sitios web dinámicos sea pan comido.

En este artículo, profundizaremos en algunas de las opciones más populares para extraer datos de esos sitios web basados en JavaScript con Scrapy. Y para facilitar aún más las cosas, te proporcionaremos ejemplos de cómo utilizar cada una de ellas para que puedas abordar con confianza cualquier sitio web que se te presente.

Si eres nuevo en Scrapy, no te preocupes. Puedes consultar nuestra guía para una introducción al web scraping con Scrapy

Si no estás familiarizado con los navegadores sin interfaz, déjame explicártelo. Básicamente, son navegadores web que funcionan sin una interfaz visible. Sí, sé que suena raro no poder ver la ventana del navegador cuando lo estás usando. Pero créeme, los navegadores sin interfaz pueden suponer un verdadero cambio de juego cuando se trata de extraer datos de la web.

He aquí el motivo: a diferencia de los navegadores normales, que simplemente muestran páginas web, los navegadores sin interfaz pueden ejecutar JavaScript. Esto significa que, si estás intentando extraer datos de un sitio web que utiliza JavaScript para generar su contenido, un navegador sin interfaz puede ayudarte ejecutando el JavaScript y permitiéndote extraer el HTML resultante.

Explorar diferentes soluciones

La mejor estrategia para renderizar JavaScript con Scrapy depende de tus necesidades y recursos específicos. Si tu presupuesto es ajustado, te interesará elegir una solución que sea rentable. Usar un navegador sin interfaz gráfica o una biblioteca de renderización de JavaScript podría ser la opción más económica, pero aún así tendrás que lidiar con la posibilidad de bloqueos de IP y el coste de mantener y ejecutar la solución.

Siempre es mejor probar varias opciones diferentes y ver cuál funciona mejor para tu caso de uso.

Cómo ejecutar JavaScript con Scrapy utilizando Splash

Splash es un navegador ligero y sin interfaz gráfica diseñado específicamente para el web scraping. Se basa en el motor WebKit, el mismo que utiliza el navegador Safari. Lo mejor de Splash es que es fácil de configurar, especialmente si utilizas Docker. Además, está integrado con Scrapy a través del middleware scrapy-splash.

Para utilizar el middleware, primero tendrás que instalar este paquete con pip:

$ pip install scrapy-splash

Configurar Splash con Docker es fácil. Solo tienes que ejecutar una instancia de Splash en tu máquina local utilizando Docker (https://docs.docker.com/get-docker/).

$ docker run -p 8050:8050 scrapinghub/splash

Después de eso, deberías poder acceder a la instancia local de Splash en http://localhost:8050/

Splash cuenta con una API REST que facilita su uso con Scrapy o cualquier otra herramienta de web scraping. Puedes probar el servidor realizando una solicitud fetch dentro del shell de Scrapy:

fetch('http://localhost:8050/render.html?url=<target_url>')

Para configurar el middleware, añade las siguientes líneas a tu archivo settings.py.

SPLASH_URL = 'http://localhost:8050'

DOWNLOADER_MIDDLEWARES = {

    'scrapy_splash.SplashCookiesMiddleware': 723,

    'scrapy_splash.SplashMiddleware': 725,

    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,

}

SPIDER_MIDDLEWARES = {

    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,

}

DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

Visita https://github.com/scrapy-plugins/scrapy-splash para obtener más información sobre cada configuración.

La forma más sencilla de procesar solicitudes con Splash es utilizar scrapy_splash.SplashRequest dentro de tu araña:

import scrapy

from scrapy_splash import SplashRequest

class RandomSpider(scrapy.Spider):

    name = 'random_spider'

    def start_requests(self):

        start_urls = [

        '<first_url',

        '<second_url>'

       ]

        for url in start_urls:

           yield SplashRequest(url=url, callback=self.parse, args={'wait': 5})

    def parse(self, response):

       

            result = response.css("h3::text").extract()

         

            yield result

Puedes añadir un parámetro «wait» para especificar el tiempo que quieres que Splash espere antes de devolver tu solicitud.

Una posible desventaja de utilizar Splash es que requiere el uso del lenguaje de scripting Lua para realizar acciones como hacer clic en botones, rellenar formularios y navegar por páginas.

Cómo ejecutar JavaScript con Scrapy utilizando Selenium

Puedes utilizar Scrapy con el controlador web de Selenium. El middleware scrapy-selenium funciona inyectando el controlador web de Selenium en el proceso de solicitud, de modo que el HTML resultante se devuelve a la araña para su análisis.

Antes de implementar esta solución, es importante tener en cuenta que necesitarás instalar un controlador web para interactuar con un navegador. Por ejemplo, necesitarás instalar geckodriver para utilizar Firefox con Selenium. Una vez que tengas instalado un controlador web, podrás configurar Selenium en los ajustes de tu proyecto de Scrapy:

SELENIUM_DRIVER_NAME = 'firefox'

SELENIUM_DRIVER_EXECUTABLE_PATH = which('geckodriver')

SELENIUM_DRIVER_ARGUMENTS=['-headless']  # '--headless' if using chrome instead of firefox

DOWNLOADER_MIDDLEWARES = {

    'scrapy_selenium.SeleniumMiddleware': 800

}

ITEM_PIPELINES = {

    'myproject.pipelines.SanitizePipeline': 1,

}

A continuación, puede configurar su araña:

import scrapy

from scrapy_selenium import SeleniumRequest

class RandomSpider(scrapy.Spider):

    name = 'random_spider'

    def start_requests(self):

        start_urls = [

        '<first_url',

        '<second_url>'

       ]

        for url in start_urls:

            yield SeleniumRequest(url=url, callback=self.parse)

    def parse(self, response):

            print(response.request.meta['driver'].title)

            #The request will be handled by selenium, and the request will have an additional meta key, named driver containing the selenium driver with the request processed.

       

            result = response.selector.css("#result::text").extract()

            #The selector response attribute work as usual (but contains the  html processed by the selenium driver).

         

            yield result

Para obtener más información sobre los métodos y atributos de controladores disponibles, consulta la documentación de Selenium para Python:

http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webdriver

Selenium requiere que haya un navegador web instalado en la máquina en la que se ejecuta, ya que no es un navegador sin interfaz de usuario independiente. Esto dificulta su implementación y ejecución en múltiples máquinas o en un entorno en la nube.

Cómo ejecutar JavaScript con Scrapy utilizando WebScrapingApi

WebScrapingAPI proporciona una API que se encargará de todo el trabajo pesado por ti. Puede ejecutar JavaScript, rotar proxies e incluso gestionar CAPTCHAs, asegurando que puedas rastrear sitios web con facilidad. Además, nunca tendrás que preocuparte de que te bloqueen la IP por enviar demasiadas solicitudes. Para configurar Scrapy para que funcione con WebScrapingAPI, configuraremos un middleware de proxy que tunelizará todas las solicitudes de obtención a través de WSA.

Para ello, configuraremos Scrapy para que se conecte al servidor proxy de WSA:

import base64

# add this to your middlewares.py file

class WSAProxyMiddleware:

    def process_request(self, request, spider):

        # Set the proxy for the request

        request.meta['proxy'] = "http://proxy.webscrapingapi.com:80"

        request.meta['verify'] = False

        # Set the proxy authentication for the request

        proxy_user_pass = "webscrapingapi.render_js=1:<API_KEY>"

        encoded_user_pass = base64.b64encode(proxy_user_pass.encode()).decode()

        request.headers['Proxy-Authorization'] = f'Basic {encoded_user_pass}'

Y habilitaremos el middleware:

DOWNLOADER_MIDDLEWARES = {

    'myproject.middlewares.WSAProxyMiddleware': 1,

}

webscrapingapi.render_js=1 es el nombre de usuario de autenticación del proxy, <API_KEY> la contraseña.

Puedes obtener una API_KEY gratuita creando una nueva cuenta en https://www.webscrapingapi.com/

Al especificar el parámetro render_js=1, habilitarás la capacidad de WebScrapingAPI para acceder a la página web de destino utilizando un navegador sin interfaz gráfica, lo que permite que los elementos de JavaScript de la página se rendericen antes de devolverte el resultado final del scraping.

También puede indicar a WSA que realice una acción específica al procesar su URL. Para ello, especifique el parámetro js_instructions:

js_instructions=[

{"action":"click","selector":"button#log-in-button"}

]

// esta secuencia se podría utilizar para hacer clic en un botón

Y eso es todo, WSA ahora realizará automáticamente todas las solicitudes por ti.

Conclusión

Extraer datos de sitios web dinámicos puede ser una tarea complicada, pero con las herramientas adecuadas, se vuelve mucho más manejable. En este artículo, hemos analizado tres opciones diferentes para extraer datos de sitios web dinámicos con Scrapy. Los navegadores sin interfaz gráfica, como Splash y Selenium, te permiten ejecutar JavaScript y renderizar páginas web igual que un navegador normal. Sin embargo, si quieres ir por el camino fácil, utilizar una API como WebScrapingApi también puede ser una gran solución. Se encarga de todas las tareas complejas por ti y te permite extraer datos fácilmente incluso de los sitios web más difíciles. Independientemente de la opción que elijas, es importante tener en cuenta tus necesidades específicas y elegir la solución que mejor se adapte a tu proyecto. ¡Gracias por leer y feliz scraping!

Acerca del autor
Mihai Maxim, Desarrollador Full Stack @ WebScrapingAPI
Mihai MaximDesarrollador Full Stack

Mihai Maxim es desarrollador full stack en WebScrapingAPI, donde colabora en todas las áreas del producto y ayuda a crear herramientas y funciones fiables para la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.