class: center, middle, inverse, title-slide # Web Scraping, Web Services e API’s ## Extraindo dados através do R ###
Lucas da Cunha Godoy ###
2018/10/16 --- class: middle center bg-main1 # **1º Datathon - UFRGS ** -- <br> # Web Scraping, Web Services e API's #
-- <img src="images/img1.jpg" width="40%"> --- class: bg-main1 split-30 hide-slide-number .column.bg-main3[ ] .column.slide-in-right[ .sliderbox.bg-main2.vmiddle[ .font5[Intro ] ]] --- class: split-two .column.bg-main1[ .split-three[ .row.bg-main1[.content.vmiddle.center[ ## Web Scraping ]] .row.bg-main2[.content.vmiddle.center[ ## Web Service ]] .row.bg-main3[.content.vmiddle.center[ ## API ]] ]] .column.bg-black.indigo[.content.vmiddle.center[ ### Características <br> ### Pacotes <br> ### Quando utilizar <br> ]] --- class: split-two gray-row3-col1 gray-row2-col1 count: false .column.bg-main1[ .split-three[ .row.bg-main1[.content.vmiddle.center[ ## Web Scraping ]] .row.bg-main2[.content.vmiddle.center[ ## Web Service ]] .row.bg-main3[.content.vmiddle.center[ ## API ]] ]] .column.bg-black.indigo[.content.vmiddle[ ### Características - Extração de dados de páginas web - HTTP ou Navegador Web ### Pacotes - `RSelenium` - `rvest` ### Quando utilizar - Dados não estruturados - Dados não divulgados via API e Web Service - SINAM, Wikipédia, etc. ]] --- class: split-two gray-row3-col1 gray-row1-col1 count: false .column.bg-main1[ .split-three[ .row.bg-main1[.content.vmiddle.center[ ## Web Scraping ]] .row.bg-main2[.content.vmiddle.center[ ## Web Service ]] .row.bg-main3[.content.vmiddle.center[ ## API ]] ]] .column.bg-black.indigo[.content.vmiddle[ ### Características - Bases de dados disponíveis na web - URL's parametrizadas ### Pacotes - Não necessariamente necessita de um pacote específico. Entretanto, `jsonlite` pode ajudar caso os dados sejam retornados em forma de json. ### Quando utilizar - Bases públicas nas quais as URLs seguem padrões de acordo com os parâmetros solicitados. - Exemplos: * Portal da Transparência; * IBGE ]] --- class: split-two gray-row1-col1 gray-row2-col1 count: false .column.bg-main1[ .split-three[ .row.bg-main1[.content.vmiddle.center[ ## Web Scraping ]] .row.bg-main2[.content.vmiddle.center[ ## Web Service ]] .row.bg-main3[.content.vmiddle.center[ ## API ]] ]] .column.bg-black.indigo[.content.vmiddle[ ### Características - Application Programming Interface - Muito parecido com web service - Melhor documentado ### Pacotes - Assim como web services, APIs não precisam de um pacote específico. Contudo, recomenda-se utilização do pacote `jsonlite` - `rtweet` ### Quando utilizar - Sempre que disponível. ]] --- class: split-three .row.bg-main1[.content.vmiddle.center[ # API ]] .row.bg-main2[.content.vmiddle.center[ # Web Service ]] .row.bg-main3[.content.vmiddle.center[ # Web Scrapping ]] --- class: bg-main1 split-30 hide-slide-number .column.bg-main4[ ] .column.slide-in-right[ .sliderbox.bg-main3.vmiddle[ .font5[Exemplos] ]] --- class: bg-main1 split-30 hide-slide-number center middle
# Web Scraping --- class: bg-main1 middle .center[ ## HTML ### *Hipertext Markup Language* ] * Linguagem para estruturar conteúdos para navegadores da web; * Armazenada em arquivos de texto com o sufixo _html_. --- class: bg-main1 middle ## Elementos Comuns * **html** - Todo conteúdo da página faz parte deste elemento; * **head** - Contém os metadados do documento (Título, Scripts, etc); * **title** - Título do documento (mostrado acima da página e quando é marcada como favorito); * **body** - Tudo que não está no head deve ser incluído no body, se trata do conteúdo visível primário; * **h1, h2, h3, h4** - Títulos em diferentes níveis para a página; * **p** - *Um parágrafo*; * **ul, ol, li** - lista não ordenada, lista ordenada e especificação de elementos da lista, respectivamente; --- class: bg-main1 ## Utilizando o pacote `RSelenium` ```r require(RSelenium) cDr <- wdman::chrome(port = 4444L, verbose = F) remDr <- remoteDriver(browserName = "chrome", port = 4444L) #---- IDH - Wikipedia ---- # Abre o navegador remDr$open() remDr$navigate("https://pt.wikipedia.org/wiki/Lista_de_munic%C3%ADpios_do_Brasil_por_IDH") tabela_idh <- remDr$findElement(using = 'css selector', value = '#mw-content-text > div > table.wikitable.sortable.jquery-tablesorter') (tabela_idh <- tabela_idh$getElementAttribute(attrName = 'outerHTML')) (tabela_idh <- XML::htmlTreeParse(tabela_idh[[1]], useInternalNodes = T, encoding = "UTF-8")) (tabela_idh <- XML::readHTMLTable(doc = tabela_idh, header = T, which = 1, as.data.frame = T)) ``` --- class: bg-main1 ## Utilizando o pacote `rvest` ```r require(rvest) html <- read_html(x = "https://pt.wikipedia.org/wiki/Lista_de_munic%C3%ADpios_do_Brasil_por_IDH", encoding = "UTF-8") tabela <- html %>% html_nodes(x = ., xpath = '//*[@id="mw-content-text"]/div/table[1]') %>% html_table(x = ., dec = ',') ``` --- class: bg-main1 split-two ## Resultados <br> ### `RSelenium` .center[
] <br> ### `rvest` .center[
] --- class: bg-main2 split-30 hide-slide-number center middle
# Web Service --- class: bg-main2 ## Portal da Transparência do Governo Federal -- - http://www.portaltransparencia.gov.br/download-de-dados/orcamento-despesa/2017 - http://www.portaltransparencia.gov.br/download-de-dados/orcamento-despesa/2018 -- <br> - http://www.portaltransparencia.gov.br/download-de-dados/receitas/2018 - http://www.portaltransparencia.gov.br/download-de-dados/receitas/2014 -- <br> - http://www.portaltransparencia.gov.br/download-de-dados/cpgf/201801 - http://www.portaltransparencia.gov.br/download-de-dados/cpgf/201802 -- <br> - http://www.portaltransparencia.gov.br/download-de-dados/cpcc/201702 - http://www.portaltransparencia.gov.br/download-de-dados/cpcc/201502 --- class: bg-main2 ## Portal da Transparência do Governo Federal ### Dados do Orçamento ```r download_orcamento <- function(year = NULL, ...) { temp_dir <- tempdir() link <- ('http://www.portaltransparencia.gov.br/download-de-dados/orcamento-despesa/%d') lapply(list.files(path = temp_dir, pattern = '.csv$', full.names = T), file.remove) %>% invisible() for(i in year) { file_name <- paste0(sprintf('orcamento_%d', i), '.zip') dest <- file.path( temp_dir, file_name) file.create(dest) utils::download.file(url = sprintf(link, i), destfile = dest, quiet = T, mode = 'wb') utils::unzip(zipfile = dest, exdir = temp_dir, unzip = 'internal') } out <- lapply(list.files(path = temp_dir, pattern = '.csv$', full.names = T), function(x) { aux <- suppressWarnings(data.table::fread(x, dec = ',', sep = ';', encoding = 'Latin-1', stringsAsFactors = F)) names(aux) <- trimws(iconv(names(aux), from = 'LATIN1', to = 'ASCII//TRANSLIT'), 'b') char_fct <- which(sapply(aux, is.character)) aux[, c(char_fct) := lapply(.SD, function(x) { iconv(x, from = 'LATIN1', to = 'ASCII//TRANSLIT') }), .SDcols = char_fct] aux }) %>% data.table::rbindlist() unlink(list.files(temp_dir, full.names = T), recursive = T) return(out) } ``` --- class: bg-main2 ## Pacote para baixar dados do Portal <br> <br> <br> <br> .middle[ -
`transpbrr` -
https://github.com/stats4good/transpbrr -
https://stats4good.github.io/transpbrr ] --- class: bg-main3 split-30 hide-slide-number center middle
# API --- class: split-two .column.bg-main1[ .split-two[ .row.bg-main1[.content.vmiddle.center[ ## Twitter
]] .row.bg-main2[.content.vmiddle.center[ ## Google
]] ]] .column.bg-black.white[.content.vmiddle.center[
]] --- class: split-two gray-row2-col1 count: false .column.bg-main1[ .split-two[ .row.bg-main1[.content.vmiddle.center[ ## Twitter
]] .row.bg-main2[.content.vmiddle.center[ ## Google
]] ]] .column.bg-black.indigo[.content.vmiddle[ -
Link para obtenção do token - https://developer.twitter.com/en/apps -
Pacote R - https://rtweet.info/ ]] --- class: split-two gray-row1-col1 count: false .column.bg-main1[ .split-two[ .row.bg-main1[.content.vmiddle.center[ ## Twitter
]] .row.bg-main2[.content.vmiddle.center[ ## Google
]] ]] .column.bg-black.indigo[.content.vmiddle[ -
Link para obtenção do token - https://developers.google.com/maps/documentation/geocoding/get-api-key -
Pacote R (Opcional) - https://cran.rstudio.com/web/packages/mapsapi/vignettes/intro.html - https://cran.r-project.org/web/packages/googleAuthR/index.html ]] --- class: bg-main1 split-two ## Exemplo: Twitter
```r library(rtweet) #---- Tweets citando bolso ---- ele_nao <- search_tweets(q = "jairbolsonaro", n = 1000, lang = "pt") #---- Tweets bolso ---- tl_elenao <- get_timeline(user = "jairbolsonaro", n = 100) #---- Tweets citando haddad ---- haddad <- search_tweets(q = "Haddad_Fernando", n = 1000, lang = "pt") #---- Tweets bolso ---- tl_haddad <- get_timeline(user = "Haddad_Fernando", n = 100) # Outras opcoes de consulta #---- Multiplos termos ---- eleicoes <- search_tweets(q = "#Eleições2018 OR #Eleicoes2018 OR Eleicao 2018", n = 1000, lang = "pt") ``` --- class: bg-main2 ## Exemplo: Google
### Geolocation API ```r library(magrittr) #---- Endereco - Datathon ---- address <- 'Av. Bento Gonçalves, 9500 - Agronomia, Porto Alegre - RS, 91501-970' %>% tolower() %>% gsub(pattern = ' ', replacement = '+', x = .) # Voces precisao obter a sua propria chave no site # das APIs google google_key <- "CHAVE API" language <- 'pt-br' region <- 'BR' maps_url <- "https://maps.googleapis.com/maps/api/geocode/json?" urlArgs <- c("address" = address, "language" = language, "region" = region, "key" = google_key) # Estrutura: &variavel=valor. Exemplo: ®ion=BR web_url <- utils::URLencode(paste0(maps_url, paste0("&", paste0(names(urlArgs)), "=", paste0(urlArgs), collapse = ""))) place_request <- jsonlite::fromJSON(web_url) ``` --- class: bg-main2 ## Exemplo: Google
### Geolocation API .hmiddle[
] --- class: bg-main1 split-30 hide-slide-number .column.bg-main4[ ] .column.slide-in-right[ .sliderbox.bg-main3.vmiddle[ .font5[Concluindo] ]] --- class: bg-main1 ## Conclusões ### 1. Sempre que possível utilizar API's, por serem estáveis e bem documentadas; ### 2. Quando estiverem baixando dados de algum repositório público, verificar se as URL's não seguem um padrão lógico de modo que o processo posso ser automatizado pelo R; ### 3. Web Scraping é uma boa alternativa apenas quando estas duas últimas opções não estão disponíveis; ### 4. Combinando todas essas ferramentas podemos ter acesso à um volume expressivo de dados --- class: middle center inverse #
lcgodoy.github.io #
lucasdac.godoy@gmail.com #
github.com/lcgodoy