Web Scraping con Scala y jsoup en 2025

Descubra técnicas eficaces para extraer datos dinámicos de Pinterest utilizando Playwright y las API de raspado para un raspado web rápido y escalable.
8 min de lectura
Web Scraping With Scala blog image

Python y JavaScript dominan toda la industria del scraping. Si necesita rendimiento o portabilidad, Scala ofrece una alternativa sólida. Scala nos da una base compilada, portable y fuertemente tipada con la que trabajar.

Hoy vamos a repasar cómo hacer scraping usando Scala y jsoup. Aunque no se escribe sobre ello tan a menudo como el web scraping con Python, Scala proporciona una base sólida y herramientas de scraping decentes.

¿Por qué Scala?

Hay bastantes razones para elegir Scala en lugar de Python o JavaScript.

  • Rendimiento: Scala se compila en la JVM (Java Virtual Machine). Los compiladores traducen nuestro código a bytecode ejecutable por la máquina. Esto hace que sea intrínsecamente más rápido que Python.
  • Tipado estático: La comprobación de tipos ofrece una capa adicional de seguridad. Muchos errores comunes se detectan incluso antes de que se ejecute el programa.
  • Portabilidad: Scala se compila en bytecode JVM (Java Virtual Machine). El bytecode de la JVM puede ejecutarse en cualquier lugar donde esté instalado Java.
  • Totalmente compatible con Java: Puedes usar dependencias de Java en tu código Scala. Esto amplía enormemente el ecosistema disponible para usted.

Primeros pasos

Antes de empezar, tienes que asegurarte de que tienes Scala instalado. A continuación encontrarás instrucciones para Ubuntu, macOS y Windows.

Puede consultar la documentación completa sobre la instalación aquí.

Ubuntu

curl -fL https://github.com/coursier/coursier/releases/latest/download/cs-x86_64-pc-linux.gz | gzip -d > cs && chmod +x cs && ./cs setup

macOS

brew install coursier && coursier setup

Windows

Descargue el instalador de Scala para Windows.

Creación de un rascador

Crea una nueva carpeta de proyecto y cd en ella.

mkdir quote-scraper
cd quote-scraper

Inicializar un nuevo proyecto Scala. El comando convierte nuestra nueva carpeta en un proyecto Scala y crea un archivo build.sbt para mantener nuestras dependencias.

sbt new scala/scala3.g8

Ahora, abre build.sbt. Tendrás que añadir jsoup como dependencia. El archivo de compilación completo debería tener este aspecto.

val scala3Version = "3.6.3"

lazy val root = project
  .in(file("."))
  .settings(
    name := "quote-scraper",
    version := "0.1.0-SNAPSHOT",

    scalaVersion := scala3Version,

    libraryDependencies += "org.scalameta" %% "munit" % "1.0.0" % Test,

    libraryDependencies += "org.jsoup" % "jsoup" % "1.18.3"
  )

A continuación, copia y pega el siguiente código en tu archivo Main.scala.

import org.jsoup.Jsoup
import scala.jdk.CollectionConverters._

@main def QuotesScraper(): Unit =
  val url = "http://quotes.toscrape.com"

  try
    val document = Jsoup.connect(url).get()
    //find all objects on the page with the quote class
    val quotes = document.select(".quote")

    for quote <- quotes.asScala do
      //find the first object with the class "text" and return its text
      val text = quote.select(".text").text()
      //find the first object with the class "author" and return its text
      val author = quote.select(".author").text()
      println(s"Quote: $text")
      println(s"Author: $author")
      println("-" * 50)
  
  catch case e: Exception => println(s"Error: ${e.getMessage}")

Funcionamiento del rascador

Para ejecutar nuestro scraper, ejecute el siguiente comando desde la raíz del proyecto.

sbt run

Debería ver un resultado similar al siguiente.

Quote: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
Author: Albert Einstein
--------------------------------------------------
Quote: “It is our choices, Harry, that show what we truly are, far more than our abilities.”
Author: J.K. Rowling
--------------------------------------------------
Quote: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
Author: Albert Einstein
--------------------------------------------------
Quote: “The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
Author: Jane Austen
--------------------------------------------------
Quote: “Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
Author: Marilyn Monroe
--------------------------------------------------
Quote: “Try not to become a man of success. Rather become a man of value.”
Author: Albert Einstein
--------------------------------------------------
Quote: “It is better to be hated for what you are than to be loved for what you are not.”
Author: André Gide
--------------------------------------------------
Quote: “I have not failed. I've just found 10,000 ways that won't work.”
Author: Thomas A. Edison
--------------------------------------------------
Quote: “A woman is like a tea bag; you never know how strong it is until it's in hot water.”
Author: Eleanor Roosevelt
--------------------------------------------------
Quote: “A day without sunshine is like, you know, night.”
Author: Steve Martin
--------------------------------------------------
[success] Total time: 6 s, completed Feb 18, 2025, 8:58:04 PM

Selección con jsoup

Para encontrar elementos de la página con jsoup, utilizamos el método select( ). select() devuelve una lista de todos los elementos que coinciden con nuestro selector. Veamos cómo funciona esto en nuestro proyecto Quote Scraper.

En esta línea, usamos document.select(".quote") para devolver todos los elementos de la página con una clase de quote.

val quotes = document.select(".quote")

También podríamos escribir estos selectores con más estructura: element[attribute='some value']. Esto nos permite aplicar filtros más fuertes al buscar objetos en la página.

La línea siguiente seguiría devolviendo los mismos objetos de página, pero es mucho más expresiva.

val quotes = document.select("div[class='quote']")

Veamos otro par de instancias de select() de nuestro código. Como sólo hay un elemento de texto y un autor en cada cita, select() sólo devuelve un objeto de texto y un autor. Si nuestro elemento cita contuviera varios textos o autores, devolvería todos los textos y autores de cada cita.

//find objects with the class "text" and return their text
val text = quote.select(".text").text()
//find objects with the class "author" and return their text
val author = quote.select(".author").text()

Extracción con jsoup

Para extraer datos con jsoup, podemos utilizar los siguientes métodos:

  • texto(): Extrae el texto de una lista de elementos de la página. Al extraer precios de un sitio web, estos aparecen en la página como texto.
  • attr(): Extrae un atributo específico de un único elemento de la página. Se trata de fragmentos de datos situados dentro de las etiquetas HTML. Este método se utiliza habitualmente para extraer enlaces de una página web.

texto()

Vimos ejemplos de esto con nuestro scraper inicial. text() devuelve el texto de cualquier elemento sobre el que lo invoquemos. Si el ejemplo siguiente fuera encontrar dos autores, text() extraería el texto de ambos y los combinaría en una sola cadena.

//find objects with the class "text" and return their text
val text = quote.select(".text").text()
//find objects with the class "author" and return their text
val author = quote.select(".author").text()

attr()

El método attr() se comporta de forma diferente a text(). Este método extrae un único atributo de un único elemento de página.

//find link elements with the class "tag" and extract the "href" from the first one
val firstTagLink = quote.select("a[class='tag']").attr("href")

Una vez añadida esta línea, el resultado será el siguiente.

Quote: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
Author: Albert Einstein
First Tag Link: /tag/change/page/1/
--------------------------------------------------
Quote: “It is our choices, Harry, that show what we truly are, far more than our abilities.”
Author: J.K. Rowling
First Tag Link: /tag/abilities/page/1/
--------------------------------------------------
Quote: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
Author: Albert Einstein
First Tag Link: /tag/inspirational/page/1/
--------------------------------------------------
Quote: “The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
Author: Jane Austen
First Tag Link: /tag/aliteracy/page/1/
--------------------------------------------------
Quote: “Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
Author: Marilyn Monroe
First Tag Link: /tag/be-yourself/page/1/
--------------------------------------------------
Quote: “Try not to become a man of success. Rather become a man of value.”
Author: Albert Einstein
First Tag Link: /tag/adulthood/page/1/
--------------------------------------------------
Quote: “It is better to be hated for what you are than to be loved for what you are not.”
Author: André Gide
First Tag Link: /tag/life/page/1/
--------------------------------------------------
Quote: “I have not failed. I've just found 10,000 ways that won't work.”
Author: Thomas A. Edison
First Tag Link: /tag/edison/page/1/
--------------------------------------------------
Quote: “A woman is like a tea bag; you never know how strong it is until it's in hot water.”
Author: Eleanor Roosevelt
First Tag Link: /tag/misattributed-eleanor-roosevelt/page/1/
--------------------------------------------------
Quote: “A day without sunshine is like, you know, night.”
Author: Steve Martin
First Tag Link: /tag/humor/page/1/
--------------------------------------------------
[success] Total time: 3 s, completed Feb 18, 2025, 10:29:30 PM

Herramientas alternativas de Web Scraping

  • Navegador de Scraping: Un navegador remoto totalmente integrado con proxies que puedes utilizar desde Playwright y Selenium.
  • APIs de Web Scraper: Automatice su proceso de raspado llamando a una de nuestras API. Cuando usted llama a una API de raspado, nosotros raspamos un sitio y le devolvemos los datos.
  • No Code Scraper: Díganos qué sitio quiere raspar y qué datos desea. Nosotros nos encargamos del resto.
  • Conjuntos de datos: Nuestros conjuntos de datos son quizás los más fáciles de cualquier método de extracción. Raspamos cientos de sitios y actualizamos nuestras bases de datos constantemente. Los conjuntos de datos te proporcionan un conjunto de datos limpios listos para el análisis.

Conclusión

El web scraping es bastante intuitivo con Scala. Aprendiste a seleccionar elementos de la página y extraer sus datos usando jsoup. Si el scraping no es lo tuyo, siempre puedes utilizar una de nuestras herramientas automatizadas para guiar el proceso o saltarte por completo el proceso de scraping con nuestros conjuntos de datos listos para usar.

Regístrese ahora y comience su prueba gratuita.

No se requiere tarjeta de crédito