Apresentação do problema

Na primeira atividade da aula não precisamos lidar com o conteúdo e a estrutura da página que estávamos capturando. Como o conteúdo que nos interessava estava em uma tabela, e o pacote rvest contém uma função específica para extração de tabelas, gastamos poucas linhas de código para ter a informação capturada já organizada em um data frame.

O que fazer, entretanto, com páginas que não têm tabelas? Como obter apenas as informações que nos interessam quando o conteúdo está “espalhado” pela página? Utilizaremos, como veremos abaixo, a estrutura do código HTML da própria página para selecionar apenas o que desejamos e construir data frames.

Nosso objetivo nessa atividade será capturar uma única página usando a estrutura do código HTML da página. Já sabemos que, uma vez resolvida a captura de uma página, podemos usar “loop” para capturar quantas quisermos, desde que tenham uma estrutura semelhante.

Antes disso, porém, precisamos falar um pouco sobre XML e HTML.

XML e HTML

XML significa “Extensive Markup Language”. Ou seja, é uma linguagem – e, portanto, tem sintaxe – e é uma linguagem com marcação. Marcação, neste caso, significa que todo o conteúdo de um documento XML está dentro de “marcas”, também conhecidas como “tags”. É uma linguagem extremamente útil para transporte de dados – por exemplo, a Câmara dos Deputados utiliza XML em seu Web Service para disponibilizar dados abertos (mas você não precisa saber disso se quiser usar o pacote de R bRasilLegis que desenvolvemos) – disponível aqui: https://github.com/leobarone/bRasilLegis.

Por exemplo, se quisermos organizar a informação sobre um indivíduo que assumiu diversos postos públicos, poderíamos organizar a informação da seguinte maneira:

<politicos>
  <politico>
    <id> 33333 </id>
    <nome> Fulano Deputado da Silva </nome>
    <data_nascimento> 3/3/66 </data_nascimento>
    <sexo> Masculino </sexo>
    <cargos>
      <cargo> 
        <cargo> prefeito </cargo> 
        <partido> PAN </partido>
        <ano_ini> 2005 </ano_ini>
        <ano_fim> 2008 </ano_fim>
      </cargo>
      <cargo> 
        <cargo> deputado federal </cargo> 
        <partido> PAN </partido>
        <ano_ini> 2003 </ano_ini>
        <ano_fim> 2004 </ano_fim>
       </cargo>
       <cargo> 
        <cargo> deputado estadual </cargo> 
        <partido> PAN </partido>
        <ano_ini> 1998 </ano_ini>
        <ano_fim> 2002 </ano_fim>
       </cargo>
      </cargos>
  </politicos>
</politicos>

Exercício (difícil): se tivessemos que representar estes dados em um banco de dados (data frame), como seria? Quantas linhas teria? Quantas colunas teria?

Veja no link abaixo um exemplo de arquivo XML proveniente do Web Service da Câmara dos Deputados:

http://www.camara.gov.br/SitCamaraWS/Deputados.asmx/ObterDetalhesDeputado?ideCadastro=141428&numLegislatura=

Abra agora a página inicial da Folha de São Paulo. Posicione o mouse em qualquer elemento da página e, com o botão direito, selecione “Inspecionar” (varia de navegador para navegador, mas o melhor é sempre usar o Firefox. Se estiver utilizando Internet Explorer, saia já daí). Você verá o código HTML da página.

Sem precisar observar muito, é fácil identificar que o código HTML da Folha se assemelha ao nosso breve exemplo de arquivo XML. Não por acaso: HTML é um tipo de XML. Em outra palavras, toda página de internet está em um formato de dados conhecido e, como veremos a seguir, pode ser re-organizado facilmente.

Tags, nodes, atributos, valores e conteúdo na linguagem XML

Todas as informações em um documento XML estão dispostas em “tags” (id, nome, etc são as tags do nosso exemplo). Um documento XML é um conjunto de “tags” com hierarquia. Um conjunto de “tags” hierarquicamente organizado é chamado de “node”. Por exemplo, no arquivo XML da Câmara dos Deputados apresentado acima, cada tag político contém diversos outras “tags” e formam “nodes”, ou seja, pedaços do arquivo XML.

Em geral, as “tags” vêm em pares: uma de abertura e outra de fechamento. O que as diferencia é a barra invertida presente na tag de fechamento. Entre as “tags” de abertura e fechamento vemos o conteúdo da tag, que pode, inclusive, ser outras “tags”. Veja os exemplos abaixo:

<minha_tag> Este é o conteúdo da tag </minha_tag>

<tag_pai>
  <tag_filha>
  </tag_filha>
</tag_pai>

<tag_pai> Conteúdo da tag Pai
  <tag_filha> Conteúdo da tag Filha
  </tag_filha>
</tag_pai>

Identação (espaços) nos ajudam a ver a hierarquia entre as tags, mas não é obrigatória. Também as quebras de linha são opcionais.

Além do conteúdo e do nome da tag, é extremamente comum encontrarmos “atributos” nas tags em bancos de dados e, sobretudo, em códigos HTML. Atributos ajudam a especificar a tag, ou seja, identificam qual é o seu uso ou carregam quaisquer outras informações referentes. Voltando ao exemplo fictício acima, poderíamos transformar a informação do cargo, que hoje é uma tag cargo dentro de outra tag cargo (horrível, não?) em atributo.

Em vez de:

<politicos>
  <politico>
    <id> 33333 </id>
    <nome> Fulano Deputado da Silva </nome>
    <data_nascimento> 3/3/66 </data_nascimento>
    <sexo> Masculino </sexo>
    <cargos>
      <cargo> 
        <cargo> prefeito </cargo> 
        <partido> PAN </partido>
        <ano_ini> 2005 </ano_ini>
        <ano_fim> 2008 </ano_fim>
      </cargo>
      <cargo> 
        <cargo> deputado federal </cargo> 
        <partido> PAN </partido>
        <ano_ini> 2003 </ano_ini>
        <ano_fim> 2004 </ano_fim>
       </cargo>
       <cargo> 
        <cargo> deputado estadual </cargo> 
        <partido> PRONA </partido>
        <ano_ini> 1998 </ano_ini>
        <ano_fim> 2002 </ano_fim>
       </cargo>
      </cargos>
  </politicos>
</politicos>

Teríamos:

<politicos>
  <politico>
    <id> 33333 </id>
    <nome> Fulano Deputado da Silva </nome>
    <data_nascimento> 3/3/66 </data_nascimento>
    <sexo> Masculino </sexo>
    <cargos>
      <cargo tipo = 'prefeito'>
        <partido> PAN </partido>
        <ano_ini> 2005 </ano_ini>
        <ano_fim> 2008 </ano_fim>
      </cargo>
      <cargo tipo = 'deputado federal'>
        <partido> PAN </partido>
        <ano_ini> 2003 </ano_ini>
        <ano_fim> 2004 </ano_fim>
       </cargo>
      <cargo tipo = 'deputado estadual'>
        <partido> PRONA </partido>
        <ano_ini> 1998 </ano_ini>
        <ano_fim> 2002 </ano_fim>
       </cargo>
      </cargos>
  </politicos>
</politicos>

Veja que agora a tag “cargo” tem um atributo – “tipo” – cujos valores são “prefeito”, “deputado federal” ou “deputado estadual”. Estranho, não (o webservice da Câmara dos Deputados é um repositório dessas estranhezas)? Para bancos de dados em formato XML, faz menos sentido o uso de atributos. Mas para páginas de internet, atributos são essenciais. Por exemplo, sempre que encontrarmos um hyperlink em uma página, ele estará contido sempre em uma tag de nome “a”, e veremos apenas o “texto clicável” (conteúdo), pois o hyperlink estará no atributo “href”. Veja o exemplo

<a href="http://acervo.folha.com.br/?cmpid=menupe">Acervo Folha</a>

Tente, no próprio site da Folha de São Paulo, clicar com o botão direito em um hyperlink qualquer para observar algo semelhante ao exemplo acima. Adiante vamos ver como atributos são extremamente úteis ao nosso propósito.

Caminhos no XML e no HTML

O fato de haver hierarquia nos códigos XML e HTML nos permite construir “caminhos”, como se fossem caminhos de pastas em um computador, dentro do código.

Por exemplo, o caminho das “tags” que contêm a informação “nome” em nosso exemplo fictício é:

/politicos/politico/nome 

O caminho das “tags” que contêm a informação “partido” em nosso exemplo fictício, por sua vez, é:

/politicos/politico/cargos/cargo/partido

Seguindo tal caminho chegamos às três “tags” que contém a informação desejada.

Simples, não? Mas há um problema: o que fazer quando chegamos a 3 informações diferentes (o indivíuo em nosso exemplo foi eleito duas vezes pelo PAN e uma pelo PRONA)? Há duas alternativa: a primeira, ficamos com as 3 informações armazenadas em um vetor, pois as 3 informações interessam. Isso ocorrerá com frequência.

Mas se quisermos apenas uma das informações, por exemplo, a de quando o indivíduo foi eleito deputado estadual? Podemos usar os atributos e os valores dos atributos das tag para construirmos o caminho. Neste caso, teríamos como caminho:

/politicos/politico/cargos/cargo[@tipo = 'deputado estadual']/partido

Guarde bem este exemplo: ele será nosso modelo quando tentarmos capturar páginas.

Vamos supor que queremos poupar nosso trabalho e sabemos que as únicas “tags” com nome “partido” no nosso documento são aquelas que nos interessam (isso quase nunca é verdade em um documento HTML). Podemos simplicar nosso caminho de forma a identificar “todas as ‘tags’, não importa em qual nível hierarquíco do documento”. Neste caso, basta usar duas barras:

//partido

Ou “todas as tags ‘partido’ que sejam descendentes de ‘politico’, não importa em qual nível hierarquíco do documento”:

/politicos/politico//partido

Ou ainda “todas as tags ‘partido’, , não importa em qual nível hierarquíco , que sejam descendentes de quaisquer tag ‘politico’, também não importando em qual nível hierarquíco do documento”:

//politico//partido

Ou “todas as ‘tags’ filhas de qualquer ‘tag’ ‘cargo’” (usa-se um asterisco para indicar ‘todas’):

//cargo/*

Observe o potencial dos “caminhos” para a captura de dados: podemos localizar em qualquer documento XML ou HTML uma informação usando a própria estrutura do documento. Não precisamos organizar o documento todo, basta extrair cirurgicamente o que queremos – o que é a regra na raspagem de páginas de internet.

Capturar uma página e examinar sua estrutura

O primeiro passo na captura de uma página de internet é criar um objeto que contenha o código HTML da página. Para tanto, usamos a função read_html do pacote rvest, que utilizamos na aula anterior. Vamos usar a segunda página da busca pela palavra “merenda” na Folha de São Paulo como exemplo:

library(rvest)

url_folha <- 'http://search.folha.uol.com.br/search?q=merenda&site=todos&results_count=3769&search_time=0.033&url=http%3A%2F%2Fsearch.folha.uol.com.br%2Fsearch%3Fq%3Dmerenda%26site%3Dtodos&sr=26'

pagina <- read_html(url_folha)

Note que a estrutura do endereço URL é relativamente simples: “q” é o primeiro parâmetro e informa o texto buscado. “site=todos”, informa que a busca é feita em todas as páginas do grupo Folha/UOL. “results_count”, é o total de resultados e “search_time” o tempo que demorou para realização da busca. “url” é o próprio endereço. E, muito importante, “sr” é o número do primeiro resultado da página, que, no caso da Folha, pula de 25 em 25. Nesta atividade vamos capturar apenas a página 2, mas você já aprendeu na atividade anterior como capturar todas as páginas usando loops.

class(pagina)

Observe (usando a função “class”) que o objeto “pagina” que contém o HTML da página em análise pertence às classes “xml_document” e “xml_node”. Ou seja, o R sabe que este objeto é um XML e, portanto, é capaz de identificar a estrutura do documento – tags, atributos, valores e conteúdos.

Extraindo os conteúdos de uma página com a biblioteca rvest

Vamos agora aprender a “navegar” em um objeto XML dentro do R e extrair dele apenas as informações que nos interessam. Estas informações podem estar no conteúdo das tags (“text”) ou nos atributos (“attr”).

Voltando ao nosso exemplo da busca na Folha de São Paulo, vamos obter os títulos e os links das notícias, cujo caminho construímos acima. Já temos o conteúdo da página capturado no objeto “pagina”.

Em primeiro lugar, com o caminho do título e a função html_nodes, extraímos os “nodes” com as “tags” que nos interessam. Além disso, convém especificar a última ‘div’ do xpath, pois há mais de uma.

nodes_titulos <- html_nodes(pagina, xpath = '//ol/li/div/div[@class="c-headline__content"]/a/h2')

Use a função “print” para observar o que capturamos.

Agora, tendo apenas os “nodes” que nos interessam por conter os títulos das notícias (e seus elementos clicáveis), usamos a função html_text para extrair os títulos:

titulos <- html_text(nodes_titulos)

View(titulos)

E a função html_attr para extrair os atributos “href”, que contêm os títulos das notícias. Vamos repetir o caminho para chegar aos links, mas retiraremos o ‘h2’ do final do caminho.

nodes_links <- html_nodes(pagina, xpath = '//ol/li/div/div[@class="c-headline__content"]/a')

links <- html_attr(nodes_titulos, name = "href")

Note que uma “tag” pode conter mais de um atributo e por isso usamos o argumento “name” da função html_attr para especificar qual atributo queremos.

Veja que as funções html_text e html_attr cumprem a mesma tarefa da função html_table: retirar de um objeto XML (que é uma página capturada) as informações que nos interessam.

O resultado de ambas funções é um vetor com todos os títulos e links das notícias, respectivamente. Podemos colocar os vetores lado a lado (verticalmente) e criar um data_frame que contém duas variáveis, título e link da notícia:

tabela_titulos <- data.frame(titulos, links)

Use a função View para visualizar os dados capturados.

O desafio a partir de agora é conectar o que aprendemos da raspagem de dados de várias páginas com “for loop”, mas usando a função html_table, com as novas funções de raspagem de páginas que extraem com precisão o que conteúdo que nos interessa. Esta será nossa próxima atividade.