Web Scraping de dados BCB

Bom dia, pessoal!

Sou novo nesse lance de web scraping e gostaria de uma sugestão de vocês.

Preciso baixar os arquivos .csv dos dados estatutários das cooperativas de crédito no Banco Central do Brasil. Para baixar estes dados, é preciso fazer o seguinte procedimento:

Acessar https://www.bcb.gov.br/estabilidadefinanceira/encontreinstituicao -> Selecionar Cooperativa de Crédito na lista Segmento -> Clicar em Pesquisar -> Clicar no Primeiro resultado -> Clicar em Órgãos Estatutários -> Clicar em Baixar csv -> salvar o csv com o cnpj no nome do arquivo

E repetir esse processo para todos os resultados da pesquisa.

A única forma que consigo pensar em fazer isso é utilizando Selenium. Fazendo um loop pra ir para o próximo item da pesquisa e repetir o procedimento, click a click.

Mas penso que talvez exista alguma outra forma mais simples que não consegui pensar. Inspecionando o console, vi que tem as partes:

início pesquisar 
POST -> rest/pessoasJuridicas 
pesquisar instituicao: instituições 20 (0/44) 
GET -> angularUtils.directives.dirPagination.template 
detalhar
id 249771 
cnpj 05790149 
instituicao.segmento [object Object] 
instituicao.segmento.id 9 
segmento 9 
GET -> rest/pessoasJuridicas 
GET -> negocio/instituicao/instituicaoDetalhe.html 
$scope.instituicaoDetalhe 
Object { id: 249771, cnpj: 5790149, nome: "CENTRAL COOPERATIVA DE CRÉDITO NO ESTADO DO ESPÍRITO SANTO - CECOOP", codigoCompensacao: 114, classeCooperativa: {…}, segmento: {…}, naturezaJuridica: "Sociedade Cooperativa", situacao: "Autorizada em Atividade", regimeEspecial: false, endereco: {…}, … }

ESTADOS  Array [ ]
Municípios Array [] 
PAISES  Array []
STATE NAME 
Object { url: "/instituicao-detalhe/{cnpj}", templateUrl: "negocio/instituicao/instituicaoDetalhe.html", controller: "instituicaoDetalheController", params: {…}, resolve: {…}, name: "instituicaoDetalhe", "$$state": $$state()
 }

GET -> uib/template/tabs/tabset.html 
GET -> rest/balanco//ultimos 
GET -> rest/estados 
GET -> rest/municipios 
GET -> rest/paises 
GET -> uib/template/tabs/tab.html 
GET -> negocio/instituicao/tabs/dadosCadastrais.html 
state instituicaoDetalhe 
substate dadosCadastrais 
  _STATE NAME 
Object { templateUrl: "negocio/instituicao/tabs/dadosCadastrais.html", controller: "instituicaoDetalheControllerDadosCadastrais", name: "instituicaoDetalhe.dadosCadastrais", "$$state": $$state()
 }

$scope.apresentaCnpj 05790149 
GET -> uib/template/tabs/tab.html 2 
got ultimos docs 
Object { 6: "202012", "$promise": {…}, "$resolved": true }

state instituicaoDetalhe.dadosCadastrais tudo.js:928:17
substate orgaos 
GET -> negocio/instituicao/tabs/orgaosEstatutarios.html angular.js:15567:41
  _STATE NAME 
Object { templateUrl: "negocio/instituicao/tabs/orgaosEstatutarios.html", controller: "instituicaoDetalheControllerOrgaos", name: "instituicaoDetalhe.orgaos", "$$state": $$state()
 }
GET -> angularUtils.directives.dirPagination.template 
Montar Estrutura CSV Órgãos

Alguém tem alguma dica de como posso fazer ou algum material para eu pesquisar sobre?

Obrigado pessoal!

EDIT--------

Encontrei uma página que exibe os dados que eu quero e assim consigo exportar em str(). Já me facilita.
Esta página é identificada pelo cnpj (no exemplo: cnpj=05790149)

str(jsonlite::fromJSON("https://www3.bcb.gov.br/informes/rest/pessoasJuridicas?cnpj=05790149"))

Mas ainda não consegui uma forma de obter todos os cnpj das cooperativas de crédito para substituir no endereço e puxar os dados.

htheodoro,

Você já tentou baixar a lista de Cooperativas de Crédito no endereço
https://www.bcb.gov.br/estabilidadefinanceira/relacao_instituicoes_funcionamento

Dai você pode carregá-la e fazer o loop para baixar os dados.

Olá, @rtheodoro! Tentei aqui e cheguei no seguinte código. Espero que ajude.

# pacotes
library(tidyverse)
library(httr)

# baixar arquivo com o cnpj das instituições
httr::GET(
  url = "https://www3.bcb.gov.br/informes/rest/pessoasJuridicas/csv?age=true",
  write_disk("inst.csv", overwrite = TRUE),
  progress()
)

# lê o arquivo
empresas <- vroom::vroom(
  file = 'inst.csv',
  skip = 7,
  delim = ";",
  locale = vroom::locale(encoding = "CP1252"),
  col_select = -last_col(), 
  .name_repair = janitor::make_clean_names) %>%
  tidyr::drop_na() %>%
  tibble::rowid_to_column("id") %>%
  dplyr::mutate(id = as.character(id))

# pega o cnpj das empresas
cnpj <- empresas %>%
  select(2) %>% 
  pull()

# algumas empresas não possuem a opção orgaos 
result <- data.frame(id = NA, nome = NA, administradores = NA)

# pega os dados do site
progressr::with_progress({
  p <- progressr::progressor(along = cnpj)
  
  base <- purrr::map_dfr(cnpj, ~ {
    
    message(.x)
    
    url <- stringr::str_glue("https://www3.bcb.gov.br/informes/rest/pessoasJuridicas?cnpj={.x}")
    
    p()
    
    parsed <- httr::GET(url) %>%
      httr::content("text") %>%
      jsonlite::fromJSON(simplifyDataFrame = TRUE) %>%
      purrr::pluck("orgaos", .default = result) %>%
      as.data.frame() %>%
      as_tibble() %>%
      tidyr::unnest(administradores, names_repair = janitor::make_clean_names)
  }, .id = "id")
})

# faz o join com a base de dados completa
df <- teste %>% 
  dplyr::left_join(cnpj, by = "id")