Web scraping com RSelenium - Investing.com

Web scraping com RSelenium - Investing.com

Raspando e salvando dados de preço de ações utilizando o R

Para quem depende de base de dados 0800, é sempre um desafio conseguir as informações desejadas. Quando se trata do site Investing.com, há duas formas de pegar dados históricos:

Forma fácil: criar um cadastro no site e baixar os dados;

Forma difícil: criar um 'robozinho' para fazer isso no seu lugar, sem criar cadastro. A vantagem é que se for 100 ações, por exemplo, o algoritmo faz todo o trabalho pesado.

Primeiro, vamos instalar e carregar os pacotes necessários:

packages = c("RSelenium","tidyverse","XML","xts")
new.packages = packages[!(packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)

suppressMessages(library(RSelenium))
suppressMessages(library(tidyverse))
suppressMessages(library(XML))
suppressMessages(library(xts))

No próximo passo, vamos definir o navegador e a função que vai fazer todo o trabalho:

driver = rsDriver(browser = "firefox") 
remote_driver = driver[["client"]] 

robot = function(ticker,indate,findate,fqc){

    # Investing
    remote_driver$navigate(paste0("https://www.investing.com/search/?q=",ticker))
    button_element = remote_driver$findElement(using = 'xpath', "//*[@id='fullColumn']/div/div[2]/div[2]/div[1]/a[1]/span[2]")
    button_element$clickElement()
    Sys.sleep(5)
    webElem <- remote_driver$findElement("css", "body")
    i=1
    while(i<4){
        webElem$sendKeysToElement(list(key = "down_arrow"))
        i=i+1
    }

    # Historical
    url = remote_driver$getCurrentUrl()
    remote_driver$navigate(paste0(url,"-historical-data")) 
    Sys.sleep(5)
    webElem <- remote_driver$findElement("css", "body")
    i=1
    while(i<9){
        webElem$sendKeysToElement(list(key = "down_arrow"))
        i=i+1
    }
    Sys.sleep(7)
    if(fqc=="daily"){
        fq = remote_driver$findElement(using = 'xpath', "//*[@id='data_interval']/option[1]")
        fq$clickElement()
    }else{
        if(fqc=="weekly"){
            fq = remote_driver$findElement(using = 'xpath', "//*[@id='data_interval']/option[2]")
            fq$clickElement()
        }else{
            if(fqc=="monthly"){
                fq = remote_driver$findElement(using = 'xpath', "//*[@id='data_interval']/option[3]")
                fq$clickElement()    
            }
        }
    }
    fq = remote_driver$findElement(using = 'xpath', "//*[@id='data_interval']/option[1]")
    fq$clickElement()
    element = remote_driver$findElement(using = 'id', "widgetFieldDateRange")
    element$clickElement()
    startDate = remote_driver$findElement(using = 'id', "startDate")
    startDate$clearElement()
    startDate$sendKeysToElement(list(indate))
    endDate = remote_driver$findElement(using = 'id', "endDate")
    endDate$clearElement()
    endDate$sendKeysToElement(list(findate))
    remote_driver$findElement(using = 'xpath', "//*[@id='applyBtn']")$clickElement()
    Sys.sleep(7)

    # Table
    tab = htmlParse(remote_driver$getPageSource()[[1]])
    tab = readHTMLTable(tab)$curr_table
    date = gsub(" ","/",tab[,1]) 
    date = gsub(",","",date)
    date = readr::parse_date(date,"%b/%d/%Y",locale=locale("en"))
    tab[,6] = gsub("M","",tab[,6])
    tab[,7] = gsub("%","",tab[,7])
    tab = apply(tab[2:7],2,as.numeric)
    tab = xts::xts(tab,order.by=date)
    write.zoo(tab,file=paste0(ticker,".csv"),sep=",")

}

A configuração do navegador pode levar alguns instantes, se der certo, vai abrir o navegador Firefox. Não precisa usar necessariamente esse navegador, mas foi que tive mais sucesso.

Basicamente, a função acima abre o site Investing, busca pelo ticker desejado, seleciona o link dos dados históricos, define o intervalo temporal, faz a busca, raspa os dados da tabela e por fim faz o download no diretório que devemos definir.

A seguir, veremos dois exemplos:

setwd("...") # Defina o diretório aqui, pois os dados serão salvos neste local.
# Exemplo 1

indate = "01/01/2017" # mm/dd/yyyy
findate = "04/21/2021" # mm/dd/yyyy
fqc = "daily" # disponíveis: "daily", "weekly", "monthly" 

robot(ticker = "PETR4", indate = "01/01/2017", findate = "04/21/2021", fqc = "daily")

# Exemplo 2
tick = read.csv("ticker.csv")

for(i in 1:length(paste0(unlist(tick)))){
    robot(ticker=paste0(unlist(tick)[i]),indate="01/01/2017",findate="04/21/2021",fqc="daily")
    pb = txtProgressBar(min = (1/length(paste0(unlist(tick)))), max = length(paste0(unlist(tick))), style = 3)
    setTxtProgressBar(pb,i)
}

# Finalizar sessão
remote_driver$close()
system("taskkill /im java.exe /f", intern=FALSE, ignore.stdout=FALSE)

Se tudo der certo, o robozinho vai trabalhar conforme exemplo abaixo:

O arquivo "ticker.csv" está disponível no meu Github.

Até a próxima!