Neste guia, abordaremos o seguinte:
O que é Jsoup?
Jsoup é um analisador de HTML em Java. Em outras palavras, a Jsoup é uma biblioteca Java que permite analisar qualquer documento HTML. Com Jsoup, você pode analisar um arquivo HTML local ou baixar um documento HTML remoto a partir de um URL.
Jsoup também oferece uma ampla gama de métodos para lidar com DOM. Em detalhes, você pode usar seletores CSS e métodos semelhantes ao jQuery para selecionar elementos HTML e extrair dados deles. Isso torna a Jsoup uma biblioteca Java eficaz na extração de dados da web para iniciantes e profissionais.
Observe que Jsoup não é a única biblioteca a realizar web scraping em Java. HTMLUnit é outra biblioteca popular de web scraping em Java . Dê uma olhada em nosso guia de HTMLUnit para web scraping em Java.
Pré-requisitos
Antes de escrever a primeira linha de código, você precisa cumprir os pré-requisitos abaixo:
- Java >= 8: qualquer versão do Java posterior ou igual à 8 servirá. É recomendável baixar e instalar uma versão LTS (suporte de longo prazo) do Java. Especificamente, este tutorial é baseado no Java 17. No momento em que este artigo foi escrito, o Java 17 era a versão LTS mais recente do Java.
- Maven ou Gradle: você pode escolher a ferramenta de automação de compilação de Java de sua preferência. Especificamente, você precisará do Maven ou do Gradle para sua funcionalidade de gerenciamento de dependências.
- Um IDE avançado com suporte a Java: qualquer IDE que suporte Java com Maven ou Gradle serve. Este tutorial é baseado no IntelliJ IDEA, que é provavelmente o melhor IDE para Java disponível.
Siga os links acima para baixar e instalar tudo o que você precisa para cumprir todos os pré-requisitos. Em ordem, configurar o Java, Maven ou Gradle e um IDE para Java. Siga os guias oficiais de instalação para evitar problemas e equívocos comuns.
Agora vamos verificar se você cumpre todos os pré-requisitos.
Verifique se o Java está configurado corretamente
Abra seu terminal. Você pode verificar se instalou o Java e configurou o Java PATH corretamente com o comando abaixo:
java -version
Esse comando deve exibir algo similar a isto:
java version "17.0.5" 2022-10-18 LTS
Java(TM) SE Runtime Environment (build 17.0.5+9-LTS-191)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.5+9-LTS-191, mixed mode, sharing)
Verifique se o Maven ou o Gradle estão instalados
Se você escolheu o Maven, execute o seguinte comando em seu terminal:
mvn -v
Você deve obter algumas informações sobre a versão do Maven que você configurou, da seguinte forma:
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: C:\Maven\apache-maven-3.8.6
Java version: 17.0.5, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk-17.0.5
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 11", version: "10.0", arch: "amd64", family: "windows"
Se você optou pelo Gradle, execute em seu terminal:
gradle -v
Da mesma forma, isso deve exibir algumas informações sobre a versão do Gradle que você instalou, conforme abaixo:
------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------
Build time: 2022-08-05 21:17:56 UTC
Revision: d1daa0cbf1a0103000b71484e1dbfe096e095918
Kotlin: 1.6.21
Groovy: 3.0.10
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.5 (Oracle Corporation 17.0.5+9-LTS-191)
OS: Windows 11 10.0 amd64
Ótimo! Agora você está pronto para aprender como fazer web scraping com Jsoup em Java!
Como criar um web scraper usando Jsoup
Aqui, você aprenderá como criar um script para web scraping com Jsoup. Esse script será capaz de extrair dados automaticamente de um site. Em detalhes, o site-alvo é o Quotes to Scrape. Se você não está familiarizado com esse projeto, ele nada mais é do que uma sandbox para web scraping.
Esta é a aparência do Quotes to Scrape:
Como você pode ver, o site-alvo simplesmente contém uma lista paginada de citações. O objetivo do web scraper em Jsoup é percorrer cada página, recuperar todas as citações e retornar esses dados no formato CSV.
Agora, siga este tutorial passo a passo do Jsoup e aprenda como criar um web scraper simples!
Etapa 1: configure um projeto Java
Aqui, você está prestes a ver como inicializar um projeto Java no IntelliJ IDEA 2022.2.3. Observe que qualquer outro IDE servirá. No IntelliJ IDEA, bastam alguns cliques para configurar um projeto Java. Inicie o IntelliJ IDEA e espere ele carregar. Em seguida, selecione a opção File > New > Project...
(arquivo > novo > projeto…) no menu superior.
Agora, inicialize seu projeto Java no pop-up New Project
(novo projeto) da seguinte forma:
Dê um nome e um local ao seu projeto, selecione Java como linguagem de programação e escolha entre Maven ou Gradle, dependendo da ferramenta de compilação que você instalou. Clique no botão Create (criar) e aguarde até que o IntelliJ IDEA inicialize seu projeto Java. Agora você deve estar vendo o seguinte projeto Java vazio:
Agora é hora de instalar a Jsoup e começar a extrair dados da web!
Etapa 2: instale a Jsoup
Se você for usuário do Maven, adicione as linhas abaixo dentro da tag dependencies
do seu arquivo pom.xml
:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
Seu arquivo pom.xml
agora deve ter a seguinte aparência:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.brightdata</groupId>
<artifactId>web-scraper-jsoup</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
</dependencies>
</project>
Alternativamente, se você for usuário do Gradle, adicione esta linha ao objeto dependencies
do seu arquivo build.gradle
:
implementation "org.jsoup:jsoup:1.15.3"
Você acabou de adicionar jsoup
às dependências do seu projeto. Agora é hora de instalá-la. No IntelliJ IDEA, clique no botão de recarga do Gradle/Maven abaixo:
Isso instalará a dependência jsoup
. Aguarde o término do processo de instalação. Agora você tem acesso a todos os recursos da Jsoup. Você pode verificar se a Jsoup foi instalada corretamente adicionando esta linha de importação no topo do seu arquivo Main.java
:
import org.jsoup.*;
Se o IntelliJ IDEA não reportar nenhum erro, isso significa que agora você pode usar a Jsoup em seu script de web scraping em Java.
Agora vamos codificar um web scraper com a Jsoup!
Etapa 3: conecte-se à sua página web de destino
Você pode usar a Jsoup para se conectar ao seu site-alvo em uma única linha de código:
// downloading the target website with an HTTP GET request
Document doc = Jsoup.connect("https://quotes.toscrape.com/").get();
Graças ao método Jsoup connect()
, você pode se conectar a um site. O que acontece nos bastidores é que a Jsoup executa uma solicitação HTTP GET para o URL especificado como parâmetro, obtém o documento HTML retornado pelo servidor de destino e o armazena no objeto Document
doc
da Jsoup.
Lembre-se de que se connect()
falhar, o Jsoup gerará uma IOException
. Isso pode ocorrer por vários motivos. No entanto, você deve estar ciente de que muitos sites bloqueiam solicitações que não envolvem um cabeçalho User-Agent
válido. Se você não está familiarizado com isso, o cabeçalho User-Agent
é um valor de string que identifica a versão do aplicativo e do sistema operacional a partir da qual uma solicitação se origina. Saiba mais sobre User-Agent
s para web scraping.
Você pode especificar um cabeçalho User-Agent
em Jsoup
da seguinte forma:
Document doc = Jsoup
.connect("https://quotes.toscrape.com/")
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
.get();
Especificamente, o método userAgent()
da Jsoup permite que você defina o cabeçalho User-Agent
. Observe que você define um valor para qualquer outro cabeçalho HTTP por meio do método header()
.
Sua classe Main.java
agora deve ter a seguinte aparência:
package com.brightdata;
import org.jsoup.*;
import org.jsoup.nodes.*;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
// downloading the target website with an HTTP GET request
Document doc = Jsoup
.connect("https://quotes.toscrape.com/")
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
.get();
}
}
Vamos começar a analisar o site-alvo para aprender como extrair dados dele.
Etapa 4: inspecione a página HTML
Se você quiser extrair dados de um documento HTML, você deve primeiro analisar o código HTML da página web. Primeiro, você precisa identificar os elementos HTML que contêm os dados que você deseja extrair. Então, você precisa encontrar uma maneira de selecionar esses elementos HTML.
Você pode conseguir tudo isso por meio das ferramentas de desenvolvedor do seu navegador. No Google Chrome ou em qualquer navegador baseado em Chromium, clique com o botão direito do mouse em um elemento HTML que mostre alguns dados de interesse. Em seguida, selecione Inspecionar.
Isso é o que você deve estar vendo agora:
Ao pesquisar o código HTML, você pode ver que cada citação está encapsulada em um elemento HTML <div>
. Em detalhes, esse elemento <div>
contém:
- Um elemento HTML
<span>
contendo o texto da citação - Um elemento HTML
<small>
contendo o nome do autor - Um elemento
<div>
com uma lista de elementos HTML<a>
contendo as tags associadas à citação.
Agora, dê uma olhada nas classes CSS usadas por esses elementos HTML. Graças a eles, você pode definir os seletores CSS necessários para extrair esses elementos HTML do DOM. Especificamente, você pode recuperar todos os dados associados a uma citação aplicando os seletores CSS em .quote
abaixo:
.text
.author
.tags .tag
Agora vamos aprender como você pode fazer isso na Jsoup.
Etapa 5: selecione elementos HTML com Jsoup
A classe Document
da Jsoup oferece várias maneiras de selecionar elementos HTML do DOM. Vamos nos aprofundar nas mais importantes.
Jsoup permite que você extraia elementos HTML com base em suas tags:
// selecting all <div> HTML elements
Elements divs = doc.getElementsByTag("div");
Isso retornará a lista de elementos HTML <div>
contidos no DOM.
Da mesma forma, você pode selecionar elementos HTML por classe:
// getting the ".quote" HTML element
Elements quotes = doc.getElementsByClass("quote");
Se você quiser recuperar um único elemento HTML com base em seu atributo id
, você pode usar:
// getting the "#quote-1" HTML element
Element div = doc.getElementById("quote-1");
Você também pode selecionar elementos HTML por um atributo:
// selecting all HTML elements that have the "value" attribute
Elements htmlElements = doc.getElementsByAttribute("value");
Ou que contenha uma parte específica do texto:
// selecting all HTML elements that contain the word "for"
Elements htmlElements = doc.getElementsContainingText("for");
Esses são apenas alguns exemplos. Lembre-se de que a Jsoup vem com mais de 20 abordagens diferentes para selecionar elementos HTML de uma página web. Veja todos eles.
Conforme aprendido anteriormente, os seletores CSS são uma forma eficaz de selecionar elementos HTML. Você pode aplicar um seletor CSS para recuperar elementos na Jsoup por meio do método select()
:
// selecting all quote HTML elements
Elements quoteElements = doc.getElementsByClass(".quote");
Como Elements
estende ArrayList
, você pode iterar sobre ele para obter cada Element
da Jsoup. Observe que você também pode aplicar todos os métodos de seleção de HTML a um único Element
. Isso restringirá a lógica de seleção aos filhos do elemento HTML selecionado.
Assim, você pode selecionar os elementos HTML desejados em cada .quote
conforme abaixo:
for (Element quoteElement: quoteElements) {
Element text = quoteElement.select(".text").first();
Element author = quoteElement.select(".author").first();
Elements tags = quoteElement.select(".tag");
}
Agora vamos aprender a extrair dados desses elementos HTML.
Etapa 6: extraia dados de uma página web com Jsoup
Primeiro, você precisa de uma classe Java na qual possa armazenar os dados extraídos. Crie um arquivo Quote.java
no pacote principal e inicialize-o da seguinte forma:
package com.brightdata;
package com.brightdata;
public class Quote {
private String text;
private String author;
private String tags;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
}
Agora, vamos estender o trecho apresentado no final da seção anterior. Extraia os dados desejados dos elementos HTML selecionados e armazene-os em objetos Quote
da seguinte forma:
// initializing the list of Quote data objects
// that will contain the scraped data
List<Quote> quotes = new ArrayList<>();
// retrieving the list of product HTML elements
// selecting all quote HTML elements
Elements quoteElements = doc.select(".quote");
// iterating over the quoteElements list of HTML quotes
for (Element quoteElement : quoteElements) {
// initializing a quote data object
Quote quote = new Quote();
// extracting the text of the quote and removing the
// special characters
String text = quoteElement.select(".text").first().text()
.replace("“", "")
.replace("”", "");
String author = quoteElement.select(".author").first().text();
// initializing the list of tags
List<String> tags = new ArrayList<>();
// iterating over the list of tags
for (Element tag : quoteElement.select(".tag")) {
// adding the tag string to the list of tags
tags.add(tag.text());
}
// storing the scraped data in the Quote object
quote.setText(text);
quote.setAuthor(author);
quote.setTags(String.join(", ", tags)); // merging the tags into a "A, B, ..., Z" string
// adding the Quote object to the list of the scraped quotes
quotes.add(quote);
}
Como cada citação pode ter mais de uma tag, você pode armazená-las todas em uma List
do Java. Em seguida, você pode usar o método String.join()
para reduzir a lista de strings a uma única string. Por fim, você pode armazenar essa string no objeto quote
.
No final do loop for
, quotes
armazenará todos os dados de citações extraídos da página inicial do site-alvo. Mas o site-alvo consiste em muitas páginas!
Vamos aprender como usar a Jsoup para rastrear um site inteiro.
Etapa 7: como rastrear o site inteiro com Jsoup
Se você olhar atentamente a página inicial do Quotes to Scrape, notará o botão “Next →” (avançar). Inspecione esse elemento HTML com as ferramentas de desenvolvedor do seu navegador. Clique com o botão direito do mouse e selecione Inspecionar.
Aqui, você pode notar que o botão “Next →” é um elemento HTML <li>
. Ele contém um elemento HTML <a>
que armazena o URL relativo para a próxima página. Observe que você pode encontrar o botão “Next →” em todas as páginas do site de destino, exceto na última. A maioria dos sites paginados segue essa abordagem.
Ao extrair o link armazenado nesse elemento HTML <a>
, você pode obter a próxima página a ter os dados extraídos. Então, se você quiser extrair dados do site inteiro, siga a lógica abaixo:
- Pesquise o elemento HTML
.next
- se estiver presente, extraia o URL relativo contido em seu filho
<a>
e vá para 2. - se não estiver presente, esta é a última página e você pode parar aqui
- se estiver presente, extraia o URL relativo contido em seu filho
- Concatene o URL relativo extraído pelo elemento HTML
<a>
com o URL base do site - Use o URL completo para se conectar à nova página
- Extraia os dados da nova página
- Vá para 1.
É disso que trata o rastreamento da web. Com a Jsoup, você pode rastrear um site paginado da seguinte forma:
// the URL of the target website's home page
String baseUrl = "https://quotes.toscrape.com";
// initializing the list of Quote data objects
// that will contain the scraped data
List<Quote> quotes = new ArrayList<>();
// retrieving the home page...
// looking for the "Next →" HTML element
Elements nextElements = doc.select(".next");
// if there is a next page to scrape
while (!nextElements.isEmpty()) {
// getting the "Next →" HTML element
Element nextElement = nextElements.first();
// extracting the relative URL of the next page
String relativeUrl = nextElement.getElementsByTag("a").first().attr("href");
// building the complete URL of the next page
String completeUrl = baseUrl + relativeUrl;
// connecting to the next page
doc = Jsoup
.connect(completeUrl)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
.get();
// scraping logic...
// looking for the "Next →" HTML element in the new page
nextElements = doc.select(".next");
}
Como você pode ver, é possível implementar a lógica de rastreamento explicada acima com um ciclo simples de while
. Bastam algumas linhas de código. Especificamente, você precisa seguir uma abordagem do... while
.
Parabéns! Agora você consegue rastrear um site inteiro. Tudo o que resta é aprender como converter os dados extraídos para um formato mais útil.
Etapa 8: exporte os dados extraídos para CSV
Você pode converter os dados extraídos para um arquivo CSV da seguinte forma:
// initializing the output CSV file
File csvFile = new File("output.csv");
// using the try-with-resources to handle the
// release of the unused resources when the writing process ends
try (PrintWriter printWriter = new PrintWriter(csvFile)) {
// iterating over all quotes
for (Quote quote : quotes) {
// converting the quote data into a
// list of strings
List<String> row = new ArrayList<>();
// wrapping each field with between quotes
// to make the CSV file more consistent
row.add("\"" + quote.getText() + "\"");
row.add("\"" +quote.getAuthor() + "\"");
row.add("\"" +quote.getTags() + "\"");
// printing a CSV line
printWriter.println(String.join(",", row));
}
}
Esse trecho converte a citação para o formato CSV e a armazena em um arquivo output.csv
. Como você pode ver, não é necessária uma dependência adicional para conseguir isso. Tudo o que você precisa fazer é inicializar um arquivo CSV com File
. Em seguida, você pode preencher com um PrintWriter
imprimindo cada quote
como uma linha formatada em CSV no arquivo output.csv
.
Note que você deve sempre fechar um PrintWriter
quando não precisar mais dele. Em detalhes, o try-with-resources
acima garantirá que a instância PrintWriter
seja fechada ao final da declaração try
.
Você começou navegando em um site e agora consegue extrair todos os dados dele para armazená-los em um arquivo CSV. Agora é hora de dar uma olhada no web scraper completo em Jsoup.
Juntando tudo
É assim que fica o script completo de web scraping da Jsoup em Java:
package com.brightdata;
import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
// the URL of the target website's home page
String baseUrl = "https://quotes.toscrape.com";
// initializing the list of Quote data objects
// that will contain the scraped data
List<Quote> quotes = new ArrayList<>();
// downloading the target website with an HTTP GET request
Document doc = Jsoup
.connect(baseUrl)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
.get();
// looking for the "Next →" HTML element
Elements nextElements = doc.select(".next");
// if there is a next page to scrape
while (!nextElements.isEmpty()) {
// getting the "Next →" HTML element
Element nextElement = nextElements.first();
// extracting the relative URL of the next page
String relativeUrl = nextElement.getElementsByTag("a").first().attr("href");
// building the complete URL of the next page
String completeUrl = baseUrl + relativeUrl;
// connecting to the next page
doc = Jsoup
.connect(completeUrl)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
.get();
// retrieving the list of product HTML elements
// selecting all quote HTML elements
Elements quoteElements = doc.select(".quote");
// iterating over the quoteElements list of HTML quotes
for (Element quoteElement : quoteElements) {
// initializing a quote data object
Quote quote = new Quote();
// extracting the text of the quote and removing the
// special characters
String text = quoteElement.select(".text").first().text();
String author = quoteElement.select(".author").first().text();
// initializing the list of tags
List<String> tags = new ArrayList<>();
// iterating over the list of tags
for (Element tag : quoteElement.select(".tag")) {
// adding the tag string to the list of tags
tags.add(tag.text());
}
// storing the scraped data in the Quote object
quote.setText(text);
quote.setAuthor(author);
quote.setTags(String.join(", ", tags)); // merging the tags into a "A; B; ...; Z" string
// adding the Quote object to the list of the scraped quotes
quotes.add(quote);
}
// looking for the "Next →" HTML element in the new page
nextElements = doc.select(".next");
}
// initializing the output CSV file
File csvFile = new File("output.csv");
// using the try-with-resources to handle the
// release of the unused resources when the writing process ends
try (PrintWriter printWriter = new PrintWriter(csvFile, StandardCharsets.UTF_8)) {
// to handle BOM
printWriter.write('\ufeff');
// iterating over all quotes
for (Quote quote : quotes) {
// converting the quote data into a
// list of strings
List<String> row = new ArrayList<>();
// wrapping each field with between quotes
// to make the CSV file more consistent
row.add("\"" + quote.getText() + "\"");
row.add("\"" +quote.getAuthor() + "\"");
row.add("\"" +quote.getTags() + "\"");
// printing a CSV line
printWriter.println(String.join(",", row));
}
}
}
}
Como mostrado aqui, você pode criar um web scraper em Java em menos de 100 linhas de código. Graças à Jsoup, você pode-se conectar a um site, rastreá-lo completamente e extrair automaticamente todos os seus dados. Em seguida, você pode gravar os dados extraídos em um arquivo CSV. É disso que trata esse web scraper da Jsoup.
No IntelliJ IDEA, inicialize o script de web scraping da Jsoup clicando no botão abaixo:
IntelliJ IDEA compilará o arquivo Main.java
e executará a classe Main
. Ao final do processo de extração, você encontrará um arquivo output.csv
no diretório raiz do projeto. Abra-o. Ele deve conter estes dados:
Muito bem! Agora você tem um arquivo CSV contendo todas as 100 citações de Quotes to Scrape! Isso significa que você acabou de aprender a criar um web scraper com a Jsoup!
Conclusão
Neste tutorial, você aprendeu o que precisa para começar a criar um web scraper, o que é a Jsoup e como usá-la para extrair dados da web. Em detalhes, você viu como usar a Jsoup para criar um aplicativo de web scraping por meio de um exemplo real. Como você aprendeu, o web scraping com Jsoup em Java envolve apenas algumas linhas de código.
No entanto, o web scraping não é tão fácil. Isso ocorre porque há vários desafios que você precisa enfrentar. Não se esqueça de que as tecnologias antibot e antiscraping estão agora mais populares do que nunca. Tudo o que você precisa é de uma ferramenta de web scraping poderosa e completa, fornecida pela Bright Data. Não quer lidar com extração de dados de maneira alguma? Dê uma olhada em nossos datasets.
Se quiser saber mais sobre como evitar bloqueios, você pode adotar um proxy com base em seu caso de uso usando um dos muitos serviços de proxy disponíveis na Bright Data. Entre em contato conosco para encontrar a solução perfeita para o seu projeto.