Análise de sentimento do COPOM com R (parte 2: replicando a base de dados)

Inspirado no artigo “Quando as palavras contam a história”, do Terraço Econômico, resolvi elaborar minha própria implementação do método, contribuindo para a comunidade. Vou mostrar então como eu fiz em alguns posts dessa série:

  1. Usando a base de dados
  2. Replicando a base de dados
  3. Analisando o sentimento

Nesse post eu vou explicar como eu fiz para baixar as atas do copom e ler elas no R.

Baixando os arquivos:

No site do Banco Central, o endereço para ver o conjunto das atas é http://www.bcb.gov.br/?ATACOPOM. Ali, você escolhe o ano que preferir para aprecer a lista de atas publicadas naquele ano. O primeiro segredo de baixar dados da internet é sempre perceber se existe algum padrão no nome dos arquivos que você quer. Pegando uma ao acaso: http://www.bcb.gov.br/?COPOM54. Uma outra: http://www.bcb.gov.br/?COPOM209. Uma terceira agora: http://www.bcb.gov.br/?COPOM101. Notaram o padrão? É sempre o mesmo endereço seguido do número da ata. Olhando no site vemos que a primeira ata é a 21 e a última a 212. Da 21 até a 199 (inclusive) as atas estão nas próprias páginas da internet e a partir da 200 são textos formatados em pdf. Vamos baixar todas para o nosso computador para não estressar o site do BCB durante as análises (e, para nós que estamos atrás do firewall, pode ser a única forma de ler o conteúdo):

library(tidyverse)

download_ata <- function(n_ata = 200) {
url = paste0(“http://www.bcb.gov.br/?COPOM&#8221;, n_ata)
if (n_ata < 200) {
destfile = paste0(“./atas/copom_”, n_ata, “.htm”)
} else {
destfile = paste0(“./atas/copom_”, n_ata, “.pdf”)
}
download.file(url = url,
destfile = destfile,
mode = “wb”,
extra = ‘-L’)
}

Criei uma função para baixar os documentos. O objetivo é baixar uma edição específica com um comando download_ata(57), por exemplo. Analisando as linhas, definimos no começo o endereço, obedecendo o formato que descobrimos, e depois escolhemos onde e com que nome vamos salvar nossa versão. Escolhi para salvar em uma subpasta “atas” da pasta de trabalho e o nome do arquivo parecido com o endereço. Note que a função escolhe, de acordo com o número se salva em html ou pdf. É importante usar a opção mode = "wb" para o pdf ficar salvo corretamente. O comando para baixar todos os arquivos seria:

seq(from = 21, to = 212) %>% map(download_ata).

Isto é, pegue a sequência numérica de 21 até 212 e aplique a função download_ata utilizando cada um destes números como argumento. Esta forma de escrever (iterativamente) evita que façamos um (lento) loop.

Lendo os arquivos:

Analisando mais profundamente os arquivos, vemos que nem todo html é igual. Os arquivos seguem uma estrutura semelhante até o número 96 e uma outra entre o 97 e o 199. Para ler os htmls vamos utilizar o pacote rvest. Vamos criar uma função para ler o arquivo, como fizemos acima. Esta função vale para os htmls mais novos. Vamos precisar também do pacote stringr. O argumento (x) é o caminho para o arquivo, por exemplo “./atas/copom_150.htm”.

extrair_html <- function(x) {
t <- read_html(x) %>%
html_nodes(“div.lista1”) %>%
html_text() %>%
str_split(“\r\r\n”) %>%
unlist() %>%
paste(collapse = ” “) %>%
str_squish()
return(t)
}

A primeira função, read_html, traz para o R todo o código HTML do arquivo. Em seguida a função html_nodes procura no documento todos os tags na forma

. Como eu sei o que procurar? Com uma página da ata aberta eu marquei um pedaço do texto e com o botão direito do mouse escolhi a opção “inspecionar elemento”. Isso faz com que o browser abra uma janela com o código da página e você possa ver o código marcado. Ele já avisa que o parágrafo do texto está marcado com esse tag. Em seguida usamos o comando html_text() para separar o texto e as funções seguintes fazem a limpeza dos parágrafos e união das linhas.

Para os htmls mais antigos usamos uma função parecida, só que o node é pior definido e acaba pegando também os nomes no começo da ata. Não faz muita diferença pra análise de sentimento porque os nomes são neutros. Para uma nuvem de palavras você vai ter que excluí-los depois:

extrair_html2 <- function(x) {

t <- read_html(x) %>%
html_nodes(“div.conteudo”) %>%
html_text() %>%
str_split(“\r\r\n”) %>%
unlist() %>%
paste(collapse = ” “) %>%
str_squish()

return(t)

}

Para ler os pdfs vamos usar o pacote pdftools. A lógica é a mesma, o primeiro comando lê o arquivo e o resto faz a limpeza. Do jeito que eu fiz aqui, ele lê TODO o texto do arquivo, mas é possível selecionar as páginas que você deseja – fica como exercício para o leitor ;).

extrair_pdf <- function(x) {
b <- pdf_text(x) %>%
str_split(“\r\n”) %>%
unlist() %>%
paste(collapse = ” “) %>%
str_squish()
return(b)
}

Por fim criamos uma função genérica que lê qualquer ata, baseado no conhecimento que temos sobre como os formatos mudam de acordo com o número da ata:

extrair_txt <- function(x) {
y <- as.integer(str_sub(x, 14, -5))
if (y < 97) {
return(extrair_html2(x))
} else {
if (y < 200) {
return(extrair_html(x))
} else {
return(extrair_pdf(x))
}
}
}

Lendo as datas:

Antes de partirmos para a criação da base de dados, queremos também ler, de forma automática, as datas de publicação destes arquivos. Como você pode imaginar o HTML é diferente do PDF, mas nem tanto. Ambos salvam de forma invísivel a data de publicação em alguma tag ou metadado escondido. No HTML fica no nó meta com o atributo content, linha 5. Descobri da mesma forma, inspecionando o arquivo. No pdf existe o comando pdf_info, onde uma das informações é a data de publicação ou de modificação. Vamos precisar também do pacote lubridate para formatar a data. O código fica assim:

datar_html <- function(x) {
z <- read_html(x) %>%
html_nodes(“meta”) %>%
html_attr(“content”) %>%
.[5] %>%
dmy() %>%
as.character()
return(z)
}

datar_pdf <- function(x) {
z <- pdf_info(x) %>%
.$modified %>%
str_sub(1, 10) %>%
ymd() %>%
as.character()
return(z)
}

extrair_data <- function(x) {
y <- as.integer(str_sub(x, 14, -5))
if (y < 200) {
return(datar_html(x))
} else {
return(datar_pdf(x))
}
}

Construindo a tabela e salvando o txt:

Para contruir a tabela vamos usar as mesmas técnicas que usamos na primeira parte do texto, com o pacote tidyverse para organizar melhor o código:

atas <- list.files(“./atas/”) %>%
as_tibble() %>%
mutate(path = paste0(“./atas/”,value)) %>%
mutate(ata = str_sub(value, 7, -5)) %>%
mutate(ata = as.integer(ata)) %>%
mutate(data = map(path, extrair_data)) %>%
mutate(data = ymd(data)) %>%
mutate(texto = map(path, extrair_txt)) %>%
arrange(data) %>%
select(-path, -value)

Vamos linha por linha. “atas” vai ser o nome da tabela que vamos criar. Primeiro pedimos uma lista de todos os arquivos da pasta das atas. Depois transformamos em um tibble que, como explicamos na primeira parte, é um tipo de dataframe. Os nomes dos arquivos formam então a primeira coluna da tabela. Em seguida criamos uma nova coluna “path” que vai ser o nome completo do arquivo, com a pasta antes. Depois criamos uma coluna “ata” que será o número da ata (baseado no nome do arquivo), e transformamos seu valor para número. O próximo passo é criar uma coluna com as datas, utilizando a função map para aplicar em cada coluna nossa função extrair_data e depois convertemos para o formato próprio de data. Criamos finalmente a coluna de texto aplicando o map para a função extrair_txt que fizemos. Para encerrar, ordenamos por data e excluímos as colunas com os nomes de arquivo. Pronto. Temos o tabelão com os textos de todas as atas, um em cada linha datada e numerada.

Para salvar o resultado em um arquivo texto igual ao nosso use o comando abaixo.

write.table(atas %>% unnest(), "atas.txt", sep = '\t', row.names = FALSE)

Você pode usar também o saveRDS() para salvar a área de trabalho do RStudio e carregas quando precisar se for mais do seu agrado. O formato texto foi usado para que eu pudesse compartilhar pela internet.

Na próxima parte vamos fazer uma pequena análise de sentimento nessa base de dados.

 

Anúncios

Um comentário sobre “Análise de sentimento do COPOM com R (parte 2: replicando a base de dados)

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 )

w

Conectando a %s