Python e JavaScript dominam todo o setor de raspagem. Se você precisar de desempenho ou portabilidade, o Scala oferece uma alternativa sólida. O Scala nos oferece uma base compilada, portátil e fortemente tipada para trabalhar.
Hoje, vamos falar sobre como fazer scraping usando Scala e jsoup. Embora não seja mencionado com tanta frequência quanto a raspagem da Web com Python, o Scala oferece uma base sólida e ferramentas de raspagem decentes.
Por que Scala?
Há vários motivos para você escolher Scala em vez de Python ou JavaScript.
- Desempenho: O Scala é compilado para a JVM (Java Virtual Machine). Os compiladores traduzem nosso código em bytecode executável por máquina. Isso o torna inerentemente mais rápido do que o Python.
- Tipagem estática: A verificação de tipos oferece uma camada adicional de segurança. Muitos bugs comuns são detectados antes mesmo de o programa ser executado.
- Portabilidade: O Scala é compilado em bytecode JVM (Java Virtual Machine). O bytecode da JVM pode ser executado em qualquer lugar em que o Java esteja instalado.
- Totalmente compatível com Java: Você pode usar dependências Java em seu código Scala. Isso amplia muito o ecossistema disponível para você.
Primeiros passos
Antes de começar, você precisa ter certeza de que tem o Scala instalado. Temos instruções abaixo para Ubuntu, macOS e Windows.
Você pode ver a documentação completa sobre a instalação aqui.
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
Faça o download do instalador do Scala para Windows.
Criando um raspador
Crie uma nova pasta de projeto e coloque um CD
nela.
mkdir quote-scraper
cd quote-scraper
Inicializar um novo projeto Scala. O comando converte nossa nova pasta em um projeto Scala e cria um arquivo build.sbt
para manter nossas dependências.
sbt new scala/scala3.g8
Agora, abra o build.sbt
. Você precisará adicionar o jsoup como uma dependência. Seu arquivo de compilação completo deve ter a seguinte aparência.
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"
)
Em seguida, copie e cole o código abaixo em seu arquivo 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}")
Executando o Scraper
Para executar nosso raspador, execute o seguinte comando na raiz do projeto.
sbt run
Você deverá ver um resultado semelhante ao abaixo.
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
Seleção com jsoup
Para localizar elementos de página com o jsoup, usamos o método select()
. select()
retorna uma lista de todos os elementos que correspondem ao nosso seletor. Vamos ver como isso funciona em nosso projeto Quote Scraper.
Nessa linha, usamos document.select(".quote")
para retornar todos os elementos da página com uma classe
de citação
.
val quotes = document.select(".quote")
Também poderíamos escrever esses seletores com mais estrutura: element[attribute='some value']
. Isso nos permite aplicar filtros mais fortes ao pesquisar objetos na página.
A linha abaixo ainda retornaria os mesmos objetos de página, mas é muito mais expressiva.
val quotes = document.select("div[class='quote']")
Vamos dar uma olhada em algumas outras instâncias de select()
do nosso código. Como há apenas um elemento de texto
e um autor
em cada citação, select()
retorna apenas um objeto de texto e um autor. Se nosso elemento de citação contivesse vários textos ou autores, ele retornaria todos os textos e autores de cada citação.
//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()
Extração com jsoup
Para extrair dados com o jsoup, podemos usar os seguintes métodos:
text()
: Extrai o texto de uma lista de elementos da página. Quando você está extraindo preços de um site, eles aparecem na página como texto.attr()
: Extrai um atributo específico de um único elemento da página. São partes de dados localizadas dentro das tags HTML. Esse método é comumente usado para extrair links de um site.
text()
Vimos exemplos disso em nosso raspador inicial. text()
retorna o texto de todos os elementos em que o chamamos. Se o exemplo abaixo fosse para encontrar dois autores, text()
extrairia o texto de ambos e os combinaria em uma única cadeia de caracteres.
//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()
O método attr()
se comporta de forma diferente de text()
. Esse método extrai um único atributo de um único item 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")
Com essa linha adicionada, nosso resultado agora tem a seguinte aparência.
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
Ferramentas alternativas de raspagem da Web
- Navegador de raspagem: Um navegador remoto totalmente integrado com proxies que você pode usar no Playwright e no Selenium.
- APIs do Web Scraper: Automatize seu processo de raspagem chamando uma de nossas APIs. Quando você chama uma API de raspador, nós raspamos um site e enviamos os dados de volta para você.
- Sem raspador de código: Informe-nos o site que você deseja extrair e os dados que deseja. Nós cuidaremos do resto.
- Conjuntos de dados: Nossos conjuntos de dados são talvez os mais fáceis de qualquer método de extração. Extraímos centenas de sites e atualizamos nossos bancos de dados o tempo todo. Os conjuntos de dados fornecem a você um conjunto limpo de dados prontos para análise.
Conclusão
A raspagem da Web é bastante intuitiva com Scala. Você aprendeu a selecionar elementos de página e extrair seus dados usando o jsoup. Se a raspagem não for sua praia, você sempre poderá usar uma de nossas ferramentas automatizadas para orientar o processo ou pular completamente o processo de raspagem com nossos conjuntos de dados prontos para uso.
Inscreva-se agora e comece seu teste gratuito hoje mesmo!
Não é necessário cartão de crédito