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 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>
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 utilizando 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.
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
Pra 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)
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.
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.
Comentários
Included file post/disqus_thread.html not found in _includes directory