Webscrapping I: Fazendo download de dados de tabelas em sites

[POST ATUALIZADO EM 03/09/2013 – Correções apontadas por Thiago Silva] Webscrapping é a tarefa de coletar dados pela internet e prepará-los para a análise de forma automatizada. Dados de diversos tipos: tabelas/bancos de dados, textos, mapas, informações geocodificadas, softwares… Neste primeiro post sobre o assunto, trago um exemplo bastante simples: baixar dados de uma tabela e transformá-los em um banco de dados em R. O script abaixo foi produzido por uma amiga há bastante tempo — e levemente modificado por mim, depois. O site-alvo é o seguinte: http://www.portaldatransparencia.gov.br/servidores/OrgaoExercicio-ListaServidores.asp?CodOS=25201&DescOS=BANCO%20CENTRAL%20DO%20BRASIL&CodOrg=25201&DescOrg=BANCO%20CENTRAL%20DO%20BRASIL&Pagina=1 A consulta gerou 278 páginas — 278 tabelas! Seria possível, claro, copiar e colar o resultado de todas as páginas em planilhas e formatá-las manualmente. Mas que trabalhinho chato! tabela A primeira dica é: percebam o padrão contido no endereço da página, reparem que ele termina com: …&Pagina=1 . Se substituirmos isso por &Pagina=2, somos direcionados para a próxima lista de resultados. Então o primeiro passo é tentar automatizar essa mudança de páginas. Em segundo lugar, as informações contidas na tabela são, na realidade, um texto HTML formatado. Ou seja, de alguma forma, estão contidas dentro do código-fonte do site. Para visualizar isso, basta clicar com o botão direito em qualquer lugar da página e selecionar a opção “Ver código fonte” (ou algo parecido, a depender do navegador). E lá está! Na linha 285: tabela Então como fazemos? Guardamos num objeto o endereço básico da HTML, substituindo o número-índice da página (&Pagina=1, &Pagina=2 etc.) por XX: 

# Endereço básico</span>
baseurl <- "http://www.portaldatransparencia.gov.br/servidores/OrgaoExercicio-ListaServidores.asp?CodOS=25201&DescOS=BANCO%20CENTRAL%20DO%20BRASIL&CodOrg=25201&DescOrg=BANCO%20CENTRAL%20DO%20BRASIL&Pagina=XX"

Depois, criamos uma função simples para retirar caracteres irrelevantes presentes no código-fonte que vai ser baixado: 

# Cria um função simples para retirar tabs e carateres especiais da página
cleanupHTML <- function(z) {
  z <- gsub("\t","",z) #retira tabs
  z <- gsub("  ", "",z) #retira espaços duplos
  z <- gsub("^\\s+", "", z) # retira espaços no início das linhas
  z <- gsub("\\s+$", "", z) # retira espaços no fim das linhas
  return(gsub("<(.|\n)*?>","",z)) #retira caracteres especiais e retorna o resultado
}

Agora, para acessar todas as 278 páginas, baixar o código-fonte, aplicar a função que “limpa” e retira os caracteres indesejados em todo material, podemos criar um loop. Esse loop substitui a expressão “XX” pelo número da página, acessa o endereço, copia o conteúdo num objeto de tipo texto (string / character), seleciona apenas as linhas que contém informações relevantes (onde estão os dados da tabela), aplica a função de limpeza e guarda os resultados:

#Loop para fazer download de uma sequencia de páginas
data <- NULL
    for (i in 1:278) { #contador: vai da página 1 à pág. 278
    print(i) #imprime na tela a página que está sendo acessada
    url <- gsub("XX", i, baseurl) #substitui a expressão XX no endereço pelo índice da página
    x <- readLines(url) #lê o código fonte da página número 'i'
    x <- iconv(x) #converte o sistema de codificação de caracteres para UTF-8
    # Este último comando funciona apenas para Windows.
    # No Linux, troque pelo seguinte comando:
    # x <- iconv(x, "latin1", "utf-8")

    #delimina as linhas inicial e final (onde estão contidos os dados desejados)
    start <- grep("<table summary=\"Lista de servidores por Nível da Função\">", x)
    end <- grep("<script type=\"text/javascript\" language=\"javascript\" src=\"../../Recursos/helper.js\"></script>", x)[1]

    x <- cleanupHTML(x[start:end]) #aplica a função que retira tabs e caracteres especiais
    data <- c(data, x) #salva os resultados num vetor
 }

O que produzimos até agora é um vetor de várias linhas, que contém, em cada uma delas, não somente os dados, como também alguns espaços vazios, células em branco e “restos” que não foram limpados pela função que montamos. Por isso, um trabalhinho adicional ainda é necessário. Além disso, em cada uma das páginas de resultado, o cabeçalho da tabela se repete. É melhor retirá-lo completamente e depois re-adicioná-lo, mas já como nome das variáveis do banco de dados que vamos compor:


temp <- data

#Retira espaços vazious e marcas de comentários
 temp <- temp[-which(temp %in% c("", " ", " ", " ", " ", " ", " "," ", " <!--", " -->"))]

#Retira cabeçalhos (pois foram coletados várias vezes -- uma vez em cada página)
 temp <- temp[-which(temp %in% c("CPF", "Nome do servidor", "Órgão de lotação"))]

#organiza os resultados como um Dataframe
 temp_m <- as.data.frame(matrix(temp, byrow=T, ncol=3))

#Dá nome às variáveis
 names(temp_m) = c("CPF", "Nome do servidor", "Órgão de lotação")

View(temp_m)

O resultado é uma banco de dados (dataframe) como este: tabela Existem outros meios de fazer esse mesmo procedimento no R (alguns mais simples, inclusive). Pacotes como o XML, RJSONIO, rjson, RCurl e RHTMLForms possuem funções que facilitam muito o webscrapping. No script acima usamos apenas as funções contidas nos pacotes básicos, que já vem com o R.

Anúncios

5 respostas em “Webscrapping I: Fazendo download de dados de tabelas em sites

  1. Pingback: Stata – Prós e Contras | Sociais & Métodos

  2. Olá Rogério, tudo bem ?
    Parabéns pelo site, estou gostando muito de ler os seus posts.

    Rogério, estou testando o codigo acima e estou encontrando um problema no terceiro bloco de comandos.Veja se consegue me ajudar.

    Loop para fazer download de uma sequencia de páginas
    data <- NULL
    for (i in 1:278) { #contador: vai da página 1 à pág. 278
    print(i) #imprime na tela a página que está sendo acessada
    url <- gsub("XX", i, baseurl) #substitui a expressão XX no endereço pelo índice da página
    x <- readLines(url) #lê o código fonte da página número 'i'
    x <- iconv(x) #converte o sistema de codificação de caracteres para UTF-8
    # Este último comando funciona apenas para Windows.
    # No Linux, troque pelo seguinte comando:
    # x <- iconv(x, "latin1", "utf-8").

    #delimina as linhas inicial e final (onde estão contidos os dados desejados)
    start <- grep("”, x)
    end <- grep("”, x)[1]

    x <- cleanupHTML(x[start:end]) #aplica a função que retira tabs e caracteres especiais
    data <- c(data, x) #salva os resultados num vetor
    }

    Essa parte do script dá o seguinte erro:
    [1] 1
    Error in start:end : argument of length 0

    • Olá Jura,

      Desculpe pela demora na resposta. Testei o código publicado originalmente e rodou certinho. Há um erro no código acima, que você reproduziu em seu comentário. As linhas que definem os objetos “start” e “end” estão incompletas. Dê uma olhada no código que está no post.

      Abraço,
      Rogério

  3. Rogério, boa noite

    Dando uma olhada no seu script, que por sinal está muito bem documentando, vi a seguinte linha

    x <- iconv(x) #converte o sistema de codificação de caracteres para UTF-8
    # Este último comando funciona apenas para Windows.
    # No Linux, troque pelo seguinte comando:
    # x <- iconv(x, "latin1", "utf-8").

    Alterei para
    # x <- iconv(x) #converte o sistema de codificação de caracteres para UTF-8
    # Este último comando funciona apenas para Windows.
    # No Linux, troque pelo seguinte comando:
    x <- iconv(x, "latin1", "utf-8")

    Tirei o comentário da ultima linha acima e também tirei o ponto no final , pois dá erro.
    Estou rodando o script em um Mac e agora deu certo.

    Obrigado.

    • De fato, aquele ponto no final dava erro! Já o removi. Obrigado pelo aviso. Sobre a marca de comentário no início, ela está ali de propósito — acabei assumindo que o usuário de Linux vai marcar como comentário a linha para o Windows e desmarcar a outra…

      abraço,
      Rogério

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s