Voltar ao blogue
Guias
Raluca Penciuc19 de outubro de 20229 minutos de leitura

Como a extração de dados da Web em R torna a ciência de dados divertida

Como a extração de dados da Web em R torna a ciência de dados divertida

Introdução ao R

O R é a versão de código aberto da linguagem de programação S, combinada com a semântica do Scheme. Surgiu pela primeira vez em meados de 1993, tornou-se de código aberto em 1995 e teve a sua primeira versão beta estável em 2000.

Cartoon meme comparing R and S Scheme with caption text expressing confusion

Ross Ihaka e Robert Gentleman conceberam o R com o objetivo de «transformar ideias em software de forma rápida e fiel».

O R é uma linguagem de programação funcional e é bem conhecida entre os cientistas de dados. Os seus casos de utilização mais populares são:

  • banca;
  • finanças;
  • comércio eletrónico;
  • aprendizagem automática;
  • qualquer outro setor que utilize grandes quantidades de dados.

Em comparação com o SAS e o SPSS, o R é a ferramenta de análise mais utilizada no mundo. A sua comunidade ativa e solidária conta com quase 2 milhões de utilizadores.

Se analisarmos algumas das empresas que integram o R nos seus negócios e a forma como o fazem, veremos:

  • Facebook: para atualizar o estado e o seu gráfico de rede social;
  • Google: para prever a atividade económica e melhorar a eficiência da publicidade online;
  • Foursquare: para o seu motor de recomendações;
  • Trulia: para prever preços de imóveis e taxas de criminalidade locais.

No entanto, em comparação com outras linguagens, o R está em constante concorrência com o Python. Ambas oferecem ferramentas de web scraping e têm comunidades ativas.

As diferenças surgem quando analisamos o público-alvo. O Python tem uma sintaxe muito fácil de aprender e muitas funcionalidades de alto nível. Isto torna-o mais apelativo para principiantes e utilizadores sem conhecimentos técnicos.

O R pode parecer um pouco intimidante à primeira vista, mas está mais focado na análise estatística. Oferece um conjunto mais vasto de ferramentas integradas de análise e visualização de dados. Assim, pode ser uma melhor opção para projetos em que se lida com grandes quantidades de dados, como o web scraping.

Sobre o rvest

O rvest está entre os pacotes mais populares usados para web scraping em R. Oferece funcionalidades de análise poderosas, mas simples. O BeautifulSoup do Python serve de fonte de inspiração e faz parte da coleção tidyverse.

Ótimo, mas porquê usar o rvest quando o R tem bibliotecas nativas que fazem o mesmo trabalho? A primeira boa razão é o facto de o rvest ser um wrapper sobre os pacotes httr e xml2. Isto significa que ele lida tanto com a solicitação GET quanto com a análise de HTML.

Assim, utiliza-se uma biblioteca em vez de duas e o código fica muito mais limpo e curto. Além disso, o rvest também pode receber uma string como entrada e tratar da análise de XML e do download de ficheiros.

No entanto, devemos ter em conta que os sites têm cada vez mais conteúdo gerado dinamicamente. As razões são diversas: desempenho, experiência do utilizador e muitas outras. O rvest não consegue lidar com a execução de JavaScript, pelo que é aqui que deve procurar uma alternativa.

Scraping com R

Bem, chega de teoria. Vamos ver como o R se comporta num caso de uso real. Para este tutorial, escolhi a página do Goodreads de um livro muito famoso: 1984, de George Orwell. Pode encontrar o site aqui: https://www.goodreads.com/book/show/61439040-1984.

Quero ver como a popularidade deste livro evoluiu ao longo dos anos. Para estimar isso, vou extrair a lista de críticas e retirar a data e a classificação de cada crítica. Como passo final, vou guardar os dados num ficheiro externo que possa ser posteriormente processado por outros programas.

Configurar o ambiente

Mas primeiro, tem de se certificar de que tem tudo o que precisa para escrever o código.

CRAN page showing download links to install R for Linux, macOS, and Windows

Quanto ao IDE, tem duas opções:

  • instalar um plugin R para o Visual Studio Code;
  • descarregar o RStudio, concebido para facilitar a programação em R.

Neste tutorial, irei utilizar a segunda opção. Pode descarregá-lo aqui: https://www.rstudio.com/products/rstudio/download/.

RStudio pricing comparison table highlighting that RStudio Desktop is free to download

A versão gratuita do RStudio Desktop é suficiente para se familiarizar com o básico. Tal como antes, siga as instruções de instalação.

Abra o RStudio e crie um novo diretório vazio. Vou escrever o código num novo ficheiro chamado «goodreads-rvest.r».

Apresentando o navegador

Agora, antes de extrair os dados, tem de identificar quais os dados que pretende. O Rvest suporta tanto seletores CSS como XPath, por isso escolha o seu. 

Se planeia iniciar projetos de scraping mais complexos, recomendo um conhecimento básico de HTML e CSS. Aqui está um bom local para começar.

Se não estiver familiarizado com HTML, existem também algumas opções não técnicas. Por exemplo, o Chrome oferece a extensão de navegador SelectorGadget. Permite-lhe clicar em qualquer ponto da página e mostra-lhe o seletor CSS para obter os dados.

No entanto, nem todos os sites são tão simples como o Goodreads. Vou optar por recuperar os dados utilizando seletores CSS encontrados através da inspeção manual do HTML.

Navegue até ao URL de destino no seu navegador e desça até à secção «Community Reviews». Em seguida, clique com o botão direito do rato e selecione «Inspecionar» para abrir as Ferramentas de Programador.

Goodreads book page with browser developer tools inspecting the community reviews section

O contentor com o ID “other_reviews” é aquele em que me vou concentrar. Agora, usa o botão “Inspecionar” para encontrar o seletor CSS para a data e classificação de uma crítica.

Goodreads review page with developer tools highlighting the review date and star rating elements

Assim, poderá observar o seguinte:

  • cada avaliação individual é um contêiner div com a classe “review”;
  • a data da avaliação é um único elemento âncora com a classe “reviewDate”;
  • a classificação da avaliação é um elemento span com a classe “staticStars”. Tem cinco elementos span como filhos, o número de estrelas que um utilizador pode definir. Vamos analisar os coloridos, que têm a classe “p10”.

Extrair as avaliações

Depois de verificar todos os pré-requisitos, pode finalmente começar a escrever o código.

install.packages('rvest')

Coloque o cursor no final da linha e prima o botão “Run” acima do editor de código. Verá na sua consola o progresso da instalação do pacote.

A instalação ocorre uma única vez, pelo que agora pode comentar ou eliminar a linha anterior:

#install.packages('rvest')

Agora tem de carregar (ou importar) a biblioteca:

library(rvest)

Vou usar a função read_html para enviar um pedido GET ao site de destino, o que irá descarregar o documento HTML necessário. Desta forma, vou descarregar o documento HTML necessário:

book_html <- read_html("https://www.goodreads.com/book/show/61439040-1984")

O resultado está agora armazenado na variável book_html, que também pode ver simplesmente digitando no console:

RStudio console output showing an HTML document object printed after fetching a page

Se, a qualquer momento, precisar de consultar a documentação oficial de uma função que pretenda utilizar, digite no console:

help(function_name) 

O RStudio abrirá um servidor HTTP com um link direto para a documentação. Para read_html, a saída será:

RStudio Help pane showing documentation for read_html and read_xml functions

Para obter a lista de avaliações, vou usar a função html_elements. Ela receberá como entrada o seletor CSS que encontrei anteriormente:

reviews <- book_html %>% html_elements('div.review')

O resultado será uma lista de nós XML, que irei iterar para obter a data e a classificação de cada elemento individual:

RStudio console output showing a list of scraped review nodes from an HTML document

Os programadores R utilizam o operador pipe “%>%” para tornar a codificação mais versátil. A sua função é passar o valor do operando esquerdo como argumento para o operando direito.

Pode encadear os operandos (como verá mais adiante neste guia), o que o ajudará a reduzir bastante o número de variáveis locais. A linha de código anterior, escrita sem o operador pipe, ficaria assim:

reviews <- html_elements(book_html, 'div.review')

Para recolher os dados, vou inicializar dois vetores fora do loop. Ao dar uma vista de olhos rápida no site, posso garantir que ambos os vetores terão o mesmo comprimento.

dates <- vector()
ratings <- vector()

Agora, enquanto percorro a lista de avaliações, procuro dois valores: data e classificação. Como viu anteriormente, a data é um elemento âncora que possui a classe reviewDate.

A classificação é um elemento span com a classe staticStars e contém cinco elementos span para cada estrela. Se o utilizador atribuiu uma estrela, então o elemento span terá o nome de classe p10, enquanto os restantes terão o nome de classe p0.

O código ficará assim:

for (review in reviews) {
  review_date = review %>% html_element('a.reviewDate') %>% html_text()
  dates <- c(dates, review_date)
 
  review_rating_element = review %>% html_element('span.staticStars')
  valid_stars = review_rating_element %>% html_elements('span.p10')
  review_rating = length(valid_stars)
  ratings <- c(ratings, review_rating)
}

Reparem na função html_element; não é um erro ortográfico. Podem usar html_elements quando quiserem extrair uma lista de nós XML e html_element para um único nó.

Neste caso, apliquei esta última a uma secção mais pequena do documento HTML (uma avaliação). Também utilizei a função html_text para me ajudar a obter o conteúdo de texto do elemento que encontrei. 

Por fim, vou juntar os dois vetores num único data frame para centralizar os dados:

result = data.frame(date = dates, rating = ratings)

E o resultado final ficará assim:

R console output showing a table of review dates and numeric ratings

Guardar os resultados

Todos sabemos que o scraping é inútil sem guardar os resultados em algum lugar. No R, para gravar num CSV basta:

write.csv(result, "reviews.csv")

O resultado tem de ser uma matriz ou uma estrutura de dados (o que já é), caso contrário, tenta-se uma conversão. Execute o código e verifique o diretório do projeto. Verá que pode abrir a tabela anterior num editor de texto, num documento do Excel, etc.

O resultado tem de ser uma matriz ou um data frame (o que já é), caso contrário, o sistema tenta uma conversão. Execute o código e verifique o diretório do projeto. Verá que pode abrir a tabela anterior num editor de texto, num documento do Excel, etc.

Escusado será dizer que a nossa lista de dados tem apenas 30 entradas. O site apresenta mais de 90 000 avaliações e mais de 3 milhões de classificações. Então, o que aconteceu? Bem, paginação.

Além disso, volte ao seu navegador e clique na segunda página. Irá notar que a lista muda, mas o URL não. Isto significa que utilizam um estado para carregar dinamicamente outra secção da lista.

Nestas situações, o rvest pode não ser útil. Em vez disso, um navegador automatizado pode ajudar a imitar o comportamento de clique para carregar o resto da lista. Um exemplo de uma biblioteca deste tipo é o RSelenium, mas vou deixar este assunto para um exercício de aprofundamento.

Conclusão

Espero que este tutorial lhe tenha dado uma base sólida para o web scraping com R. Agora pode tomar uma decisão mais fácil sobre a pilha tecnológica do seu próximo projeto.

No entanto, tenha em atenção que este artigo não abordou muitos dos desafios do web scraping. Pode encontrá-los de forma mais detalhada como conceitos neste guia autoexplicativo.

Sobre o autor
Raluca Penciuc, Desenvolvedor Full-Stack @ WebScrapingAPI
Raluca PenciucDesenvolvedor Full-Stack

Raluca Penciuc é programadora Full Stack na WebScrapingAPI, onde desenvolve scrapers, aperfeiçoa estratégias de evasão e procura formas fiáveis de reduzir a deteção nos sites-alvo.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.