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:
- 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.
- 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 getElement
ByName()
.
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.