Guia de raspagem da web com Java

Este tutorial ensina-o a configurar um projeto Gradle e a instalar uma dependência HtmlUnit. No processo, aprenderá tudo sobre a HtmlUnit e explorará algumas das suas capacidades avançadas.
11 min read
Codificação de braços robóticos na tela do computador.

HtmlUnit é um navegador sem cabeça que permite modelar páginas HTML. Depois de modelar a página programaticamente, você pode interagir com ela executando tarefas como preencher formulários, enviá-los e navegar entre páginas. Pode ser utilizado para a raspagem de dados da web para extrair dados para posterior manipulação, bem como para criar testes automatizados para verificar se o seu programa cria páginas web como esperado.

Raspagem da web com HtmlUnit


 

Para implementar a raspagem da web utilizando a HtmlUnit e o Gradle, será utilizado o IDE IntelliJ IDEA; no entanto, pode utilizar qualquer IDE ou editor de código que preferir.

O IntelliJ suporta uma integração totalmente funcional com o Gradle e pode ser descarregado no sítio de JetBrains. O Gradle é uma ferramenta de automatização de construção que suporta a construção e criação de pacotes para a sua aplicação. Também lhe permite adicionar e gerir dependências sem problemas. O Gradle e as extensões do Gradle são instalados e ativados por predefinição nas versões mais recentes do IntelliJ IDEA.

Todo o código para este tutorial pode ser encontrado neste repositório do GitHub.

Criar um projeto Gradle


 

Para criar um projeto Gradle no IntelliJ IDE, selecione Ficheiro > Novo > Projeto nas opções de menu e será aberto um novo assistente de projeto. Introduza o nome do projeto e selecione a localização desejada:

 

Tem de selecionar a linguagem Java, uma vez que vai criar uma aplicação de raspagem de dados da web em Java utilizando a HtmlUnit. Além disso, selecione o sistema de construção Gradle. Em seguida, clique em Criar. Isso criará um projeto Gradle com uma estrutura padrão e todos os arquivos necessários. Por exemplo, o arquivo build.gradle contém todas as dependências necessárias para criar este projeto:

Instalar HtmlUnit

Para instalar HtmlUnit como uma dependência, abra a janela Dependências selecionando Ver > Janelas de ferramentas > Dependências.

Em seguida, procure “htmlunit” e selecione Adicionar:

 

Você deve ser capaz de ver que HtmlUnit foi instalado na seção dependências do arquivo build.gradle:

Agora que instalou HtmlUnit, está na altura de raspar dados de páginas web estáticas e dinâmicas.

Raspar uma página estática


 

Nesta seção, aprenderá a raspar HtmlUnit Wiki, uma página web estática. Esta página web contém elementos como o título, o índice, a lista de subtítulos e o conteúdo de cada subtítulo.

Cada elemento de uma página web HTML tem atributos. Por exemplo, ID é um atributo que identifica de forma exclusiva um elemento no documento HTML completo e Nome é um atributo que identifica esse elemento. O atributo Nome não é único, e mais de um elemento no documento HTML pode ter o mesmo nome. Os elementos de uma página web podem ser identificados através de qualquer um dos atributos.

Em alternativa, também é possível identificar elementos utilizando o seu XPath. O XPath utiliza uma sintaxe semelhante a um caminho para identificar e navegar por elementos no HTML da página web.

Você usará esses dois métodos para identificar os elementos na página HTML nos exemplos a seguir.

Para raspar uma página web, você precisa criar um WebClient de HtmlUnit. O WebClient representa um navegador dentro da sua aplicação Java. Inicializar um WebClient é semelhante a iniciar um navegador para exibir a página web.

Para inicializar um WebClient, use o seguinte código:

WebClient webClient = new WebClient(BrowserVersion.CHROME);

Este código inicializa o navegador Chrome. Outros navegadores também são suportados.

Você pode obter a página web usando o método getPage() disponível no objeto webClient. Assim que tiver a página web, pode raspar os dados da página web utilizando vários métodos.

Para obter o título da página, use o método getTitleText(), conforme demonstrado no código a seguir:

String webPageURl = "https://en.wikipedia.org/wiki/HtmlUnit";
        try {

            HtmlPage page = webClient.getPage(webPageURl);
            
            System.out.println(page.getTitleText());
            
        } catch (FailingHttpStatusCodeException | IOException e) {
          
            e.printStackTrace();
            
        }

O título da página será então impresso:

HtmlUnit - Wikipedia

Para dar mais um passo em frente, vamos buscar todos os elementos H2 disponíveis na página web. Neste caso, os H2s estão disponíveis em duas seções da página:

  1. Na barra lateral esquerda, onde são apresentados os conteúdos: Como pode ver, o título da seção Conteúdo é um elemento H2.

     
  2. No corpo principal da página: Todos os subtítulos são elementos H2.

Para obter todos os H2s no corpo do conteúdo, pode utilizar o XPath dos elementos H2. Para encontrar o XPath, clique com o botão direito do rato em qualquer elemento H2 e selecione Inspecionar. Em seguida, clique com o botão direito do rato no elemento realçado e selecione Copiar > Copiar XPath completo:

 

Isto copiará o XPath para a área de transferência. Por exemplo, o elemento XPath dos H2s no corpo do conteúdo é /html/body/div[1]/div/div[3]/main/div[2]/div[3]/div[1]/h2.

Para obter todos os elementos H2 utilizando o seu XPath, pode utilizar o método getByXpath():

String xPath = "/html/body/div[1]/div/div[3]/main/div[2]/div[3]/div[1]/h2";

 String webPageURL = "https://en.wikipedia.org/wiki/HtmlUnit";
 
        try {
            HtmlPage page = webClient.getPage(webPageURL);

            //Get all the headings using its XPath+
            List<HtmlHeading2>  h2 = (List<HtmlHeading2>)(Object) page.getByXPath(xPath);
            
            //print the first heading text content
            System.out.println((h2.get(0)).getTextContent());

        } catch (FailingHttpStatusCodeException | IOException e) {
          
            e.printStackTrace();
            
        }

O conteúdo de texto do primeiro elemento H2 será impresso da seguinte forma:

Benefits[edit]

Da mesma forma, pode obter os elementos através do seu ID utilizando o método getElementById() e pode obter os elementos através do seu nome utilizando o método getElementByName().

Na seção seguinte, utilizará estes métodos para raspar uma página web dinâmica.

Raspar uma página web dinâmica usando HtmlUnit

Nesta seção, você aprenderá sobre as capacidades de preenchimento de formulários e de clicar em botões do HtmlUnit, preenchendo o formulário de início de sessão e enviando-o. Aprenderá também a navegar em páginas web utilizando o navegador sem cabeça.

Para ajudar a demonstrar a raspagem dinâmica da web, vamos utilizar o sítio web Hacker News. Eis o aspeto da página de início de sessão:

O código seguinte é o código do formulário HTML para a página anterior. Pode obter este código clicando com o botão direito do rato na etiqueta de início de sessão e clicando em Inspecionar:

 

<form action="login" method="post">
<input type="hidden" name="goto" value="news">
<table border="0">
<tbody>
<tr><td>username:</td><td><input type="text" name="acct" size="20" autocorrect="off" spellcheck="false" autocapitalize="off" autofocus="true"></td></tr>
<tr><td>password:</td><td><input type="password" name="pw" size="20"></td></tr></tbody></table><br>
<input type="submit" value="login"></form>

Para preencher o formulário utilizando HtmlUnit, obtenha a página web utilizando o objeto webClient. A página contém dois formulários: Iniciar sessão e Criar conta. Pode obter o formulário de início de sessão utilizando o método getForms().get(0). Em alternativa, pode utilizar o método getFormByName() se os formulários tiverem um nome único.

Em seguida, é necessário obter as entradas do formulário (ou seja, os campos de nome de usuário e palavra-passe) utilizando o método getInputByName() e o atributo nome.

Defina o valor do nome de usuário e da palavra-passe nos campos de entrada utilizando o método setValueAttribute() e obtenha o botão Enviar utilizando o método getInputByValue(). Também pode clicar no botão utilizando o método click().

Assim que o botão for clicado, e se o início de sessão for bem sucedido, a página de destino do botão Enviar será devolvida como o objeto HTMLPage, que pode ser utilizado para outras operações.

O código a seguir demonstra como obter o formulário, preenchê-lo e enviá-lo:

HtmlPage page = null;

String webPageURl = "https://en.wikipedia.org/wiki/HtmlUnit";

        try {
            // Get the first page

            HtmlPage signUpPage = webClient.getPage(webPageURL);

            // Get the form using its index. 0 returns the first form.
            HtmlForm form = signUpPage.getForms().get(0);

            //Get the Username and Password field using its name
            HtmlTextInput userField = form.getInputByName("acct");
            HtmlInput pwField = form.getInputByName("pw");
            
            //Set the User name and Password in the appropriate fields
            userField.setValueAttribute("draftdemoacct");
            pwField.setValueAttribute("test@12345");

            //Get the submit button using its Value
            HtmlSubmitInput submitButton = form.getInputByValue("login");

            //Click the submit button, and it'll return the target page of the submit button
            page = submitButton.click();


        } catch (FailingHttpStatusCodeException | IOException e) {
            e.printStackTrace();
        }

Assim que o formulário for enviado e o início de sessão for bem sucedido, será encaminhado para a página inicial do usuário, onde o nome de usuário é apresentado no canto direito:

O elemento do nome de usuário tem o ID “me” (eu). Pode obter o nome de usuário utilizando o método getElementById() e passar o ID “me”, como demonstrado no código seguinte:

System.out.println(page.getElementById("me").getTextContent());

O nome de usuário da página web é raspado e exibido como saída:

draftdemoacct

Em seguida, é necessário navegar para a segunda página do sítio Hacker News, clicando no botão de hiperligação Mais no final da página:

 

Para obter o objeto do botão Mais, obtenha o XPath do botão Mais utilizando a opção Inspecionar e obtenha o primeiro objeto de link utilizando o índice 0:

Clique na ligação Mais utilizando o método click(). O link será clicado e a página de destino do link será devolvida como um objeto HtmlPage:

HtmlPage nextPage = null;

        try {
            List<HtmlAnchor> links = (List<HtmlAnchor>)(Object)page.getByXPath("html/body/center/table/tbody/tr[3]/td/table/tbody/tr[92]/td[2]/a");
            
            HtmlAnchor anchor =  links.get(0);
            
            nextPage = anchor.click();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

Nesta altura, deve ter a segunda página no objeto HtmlPage.

Pode imprimir o URL da HtmlPage para verificar se a segunda página foi carregada com êxito:

System.out.println(nextPage.getUrl().toString());

A seguir está o URL da segunda página:

https://news.ycombinator.com/news?p=2

Cada página do sítio Hacker News tem trinta entradas. É por esta razão que as entradas da segunda página começam com o número de série 31.

Vamos recuperar o ID da primeira entrada na segunda página e ver se é igual a 31. Como antes,
obtenha o XPath da primeira entrada usando a opção Inspecionar. Em seguida, obtenha a primeira entrada da lista e exiba seu conteúdo de texto:

 

String firstItemId = null;

        List<Object> entries = nextPage.getByXPath("/html/body/center/table/tbody/tr[3]/td/table/tbody/tr[1]/td[1]/span");

        HtmlSpan span = (HtmlSpan) (entries.get(0));

        firstItemId = span.getTextContent();
        
        System.out.println(firstItemId);

O ID da primeira entrada agora é exibido:

31.

Este código mostra-lhe como preencher o formulário, clicar nos botões e navegar nas páginas web utilizando HtmlUnit.

Conclusão


 

Neste artigo, você aprendeu como raspar sítios estáticos e dinâmicos com HtmlUnit. Também aprendeu sobre algumas das capacidades avançadas do HtmlUnit, ao raspar páginas web e convertê-las em dados estruturados.

Ao fazer isso com um IDE como o IntelliJ IDEA, você precisa encontrar atributos de elemento inspecionando-os manualmente e escrever funções de raspagem do zero usando os atributos de elemento. Em comparação, o IDE para Raspador da Web da Bright Data fornece uma infraestrutura de proxy de desbloqueio robusta, funções de raspagem úteis e modelos de código para sítios populares. Uma infraestrutura de proxy eficiente é necessária quando se trata de raspar uma página web sem problemas de bloqueio de IP e limitação de taxa. O proxy também ajuda a emular um usuário de uma localização geográfica diferente.

Talk to one of Bright Data’s experts and find the right solution for your business.