15.5 - Scraping - Navegação Web

Uma importante atividade desempenhada por um scraper é a navegação web. A navegação consiste em abrir diferentes páginas de um site com o objetivo de coletar dados ou executar consultas.

Para alguns sites, a navegação pode ser realizada utilizando a biblioteca Net::HTTP. Com ela, um fluxo de execução do scraper poderia ser: abrir uma URL, coletar links relevantes nesta URL e abrir estes links. Para muitos sites, este fluxo é comum (pense, por exemplo, na navegação pelas categorias de um site de uma loja online).

Para alguns sites, esse fluxo só pode ser executado se a sessão do usuário for mantida durante as requisições. As técnicas mais comuns para reconhecer a sessão do usuário são: leitura de cookies ou passagem de identificador de sessão na URL. Para o primeiro caso, o cliente HTTP da sua linguagem deve implementar gerenciamento de cookies.

É possível gerenciar cookies utilizando a Net::HTTP, mas esta seria uma tarefa muito trabalhosa. Quando ela é necessária, é recomendado utilizar alguma biblioteca que implementa este gerenciamento e outras funcionalidades encontradas em um navegador. Este é o caso da biblioteca Mechanize.

Mechanize é uma biblioteca em ruby bastante usada quando é necessário o gerenciamento automático de cookies, mantém salvo os sites que visitou em um histórico e preenche formulários.

Para instalar o Mechanize, basta executar o seguinte comando no terminal:

  gem install mechanize

Abaixo são apresentados dois exemplos didáticos. O primeiro é a tentativa de implementar navegação em um site que armazena sessão, porém sem gerenciar cookies. O segundo é esta tentativa implementada com o Mechanize, que realiza gerenciamento de cookies automaticamente.

Nos exemplos abaixo usamos o serviço de demonstração httpbingo.org, que grava em um cookie o “produto” enviado e, ao acessar /cookies, devolve os cookies recebidos na requisição. Ele simula um “carrinho”: o produto só aparece se a sessão (cookie) for mantida entre as requisições.

Navegação sem gerenciamento de cookies

  require 'net/http'

  # "Adiciona um produto ao carrinho" (grava o produto em um cookie).
  # Net::HTTP.get não guarda cookies nem segue o redirecionamento, então o
  # carrinho aparecerá vazio no passo seguinte.
  uri = URI.parse 'https://httpbingo.org/cookies/set?produto=9742497'
  Net::HTTP.get(uri)

  # "Abre o carrinho" (lista os cookies enviados na requisição)
  uri  = URI.parse 'https://httpbingo.org/cookies'
  body = Net::HTTP.get(uri)

  # Grava a saída em um arquivo html (o carrinho estará vazio: {"cookies": {}})
  File.open('cart-no-cookies.html', 'w') { |f| f.write(body) }

Navegação com gerenciamento de cookies

require 'mechanize'

# Cria um novo user agent do Mechanize (funciona como uma instância de navegador)
agent = Mechanize.new

# "Adiciona um produto ao carrinho": o Mechanize segue o redirecionamento e
# guarda o cookie automaticamente.
agent.get 'https://httpbingo.org/cookies/set?produto=9742497'

# "Abre o carrinho": como o cookie é reenviado, o produto aparece na resposta.
agent.get 'https://httpbingo.org/cookies'

# Grava a saída em um arquivo html (o carrinho conterá o produto 9742497)
File.open('cart-with-cookies.html', 'w') { |f| f.write(agent.page.body) }