« HE:labs
HE:labs

Extraindo informações com Nokogiri

Postado por Thiago Borges em 15/05/2013

Uma área de grande importância na computação é a extração de dados em sistemas web. Nesse post, irei abordar o uso da gem Nokogiri para coletar essas informações, processo também conhecido por Web Scraping. Foi através desse trabalho que o Google iniciou seu império. E ainda, muitos outros cases de sucesso utilizam esta técnica para oferecer serviços.

Nokogiri é uma poderosa gem que realiza parsing de HTML e XML. Uma importante característica é a habilidade de utilizar seletores XPath e CSS3 para encontrar os nós da árvore DOM desejados. Isso faz com que o processo seja muito mais legível, fácil de acompanhar e de manter.

Como dito anteriormente, pode-se percorrer sites de compras e nele, realizar comparação de preço, listar imóveis de imobiliárias, criar API com JSON ou XML otimizadas para o consumo, dentre outras inúmeras utilidades.

Seletores

Seletores são padrões que indicam uma parte do código HTML, como se fossem endereços. Para encontrar as informações, é preciso escolher os melhores seletores para determinado problema. Um bom seletor precisa ser específico o bastante para não selecionar informações erradas, mas não tão rígido a ponto de quebrar, caso a estrutura do site mude um pouco.

O código abaixo será usado pra exemplificar os seletores:

 1 <div class="theater">
 2   <div class="desc">
 3     <h2 class="name">Kinoplex Shopping Tijuca</h2>
 4   </div>
 5 </div>
 6 <div class="theater">
 7   <div class="desc">
 8     <h2 class="name">Iguatemi</h2>
 9   </div>
10 </div>

XPath

O seletor XPath se baseia na árvore DOM para encontrar os nós. DOM é a estrutura que representa a organização dos elementos HTML e XML. O caminho do XPath é fácil de ser encontrado e substituído, mas você pode ter problemas, caso o HTML não esteja correto.

A seleção dos nomes dos cinemas acima é feita da seguinte forma:

1 require 'open-uri'
2 require 'nokogiri'
3 
4 doc = Nokogiri::HTML(File.open("cinemas.html"))
5 doc.xpath('//div[@class="desc"]/h2[@class="name"]').each do |node|
6   puts node.text
7 end

Este exemplo deve exibir "Kinoplex Shopping Tijuca" e "Iguatemi".

Caso esteja usando o Google Chrome, o XPath Helper pode ser utilizado para auxiliar na procura e teste de XPath. Com o Firebug, é possível copiar tanto o XPath quanto o CSS.

CSS

O seletor CSS do Nokogiri é o mesmo utilizado no jQuery. São verificadas, principalmente, as classes, IDs e elementos do documento.

O exemplo abaixo retorna a mesma informação do código que utiliza xpath.

1 require 'open-uri'
2 require 'nokogiri'
3 
4 doc = Nokogiri::HTML(File.open("cinemas.html"))
5 doc.css('.desc > h2.name').each do |node|
6   puts node.text
7 end

Exemplo

Para colocar em prática o que foi visto até aqui, fiz esse exemplo para listar os integrantes da HE:Labs e suas respectivas posições na empresa:

 1 require 'open-uri'
 2 require 'nokogiri'
 3 
 4 class Avassalador
 5   def initialize(node)
 6     @name = node.xpath("text()").text().strip
 7     @position = node.xpath("span/text()").text().strip
 8   end
 9   def to_s
10     "#{@name} - #{@position}"
11   end
12 end
13 
14 doc = Nokogiri::HTML(open("http://helabs.com.br/nossotime/"))
15 doc.xpath('//*[@id="time"]/div/ul/li/p').each do |node|
16   puts Avassalador.new(node)
17 end

Além dos elementos serem iteráveis, pode-se utilizar a API para navegar pelos nós da estrutura. Esta API pode ser utilizada para nós extraidos por XPath e CSS. Os métodos são:

1 node.parent           #=> nó pai. (Sobe um nível na árvore)
2 node.children         #=> nós filhos. (Desce um nível na árvore)
3 node.next_sibling     #=> próximo irmão. (Seleciona o próximo elemento no mesmo nível)
4 node.previous_sibling #=> irmão anterior. (Volta um elemento no mesmo nível)

Legalidade

Não é permitido publicar conteúdo na íntegra sem permissão. Se houver permissão, a fonte deve ser citada. Em 2005, o Google News foi processado por publicar conteúdo da AFP sem permissão. Para realizar análise de informações, a questão de direitos autorais pode ser parcialmente ignorada. Exemplo disso é o PageRank do Google que analisa o conteúdo das páginas, avalia sua relevância, mas não os reproduz.

Deve-se também respeitar as instruções do robots.txt. Nele, o scraper não pode acessar nada dentro do caminho /tmp/. :

1 User-agent: *
2 Disallow: /tmp/

É possível definir regras para User-agents específicos como o bot do Google. Clique para informações complementares.

Bônus

A gem google_movies é um exemplo de wrapper que retorna as informações sobre cinemas e filmes através do próprio Google Movies. Ela serve como uma referência bem completa e ao mesmo tempo, simples de entender o processo.

Links

Compartilhe

Sabia que nosso blog agora está no Medium? Confira Aqui!