Guia do iniciante para Web Scraping em R (usando rvest) com exemplo

Conteúdo

Introdução

Dados e informações na web estão crescendo exponencialmente. Hoje em dia, todos nós usamos o Google como nossa primeira fonte de conhecimento, se deve encontrar comentários sobre um lugar para entender um novo termo. Todas essas informações já estão disponíveis na web.

Com a quantidade de dados disponíveis na web, abre novos horizontes de possibilidades para uma Cientista de dados. Acredito firmemente que o web scraping é uma habilidade obrigatória para qualquer cientista de dados.. No mundo real, todos os dados que você precisa já estão disponíveis na internet; a única coisa que impede você de usá-los é a capacidade de acessá-los. Com a ajuda deste artigo, você também será capaz de superar essa barreira.

A maioria dos dados disponíveis na web não está disponível. Está presente em um formato não estruturado (Formato HTML) e não consigo baixar. Portanto, conhecimento e experiência são necessários para usar esses dados para, eventualmente, construir um modelo útil.

Neste artigo, vou orientá-lo através do processo de web scraping em R. com este item, você ganhará experiência para usar qualquer tipo de dado disponível na internet.

Tabela de conteúdo

  1. O que é Web Scraping?
  2. Por que precisamos de Web Scraping em Ciência de dados?
  3. Maneiras de extrair dados
  4. Pré-requisitos
  5. Raspando una página web usando R
  6. Analise dados extraídos da web

1. O que é Web Scraping?

Web scraping é uma técnica para converter os dados presentes em formato não estruturado (Tags HTML) na web para um formato estruturado que pode ser facilmente acessado e usado.

Quase todos os principais idiomas fornecem maneiras de realizar a raspagem da web. Neste artigo, usaremos R para extrair os dados dos longas-metragens mais populares de 2016 do IMDb site web.

Obteremos uma série de funções para cada uma das 100 filmes populares lançados em 2016. O que mais, Analisaremos os problemas mais comuns que podem ocorrer ao extrair dados da Internet devido a inconsistências no site.. código e veja como resolver esses problemas.

Se você se sentir mais confortável usando Python, Eu recomendo que você leia este guia para começar a raspagem da web com Python.

2. Por que precisamos de Web Scraping?

Tenho certeza de que as primeiras perguntas que devem ter surgido na sua cabeça agora são “Por que precisamos de raspagem na web”? Como eu disse antes, as possibilidades com web scraping são imensas.

Para lhe dar conhecimento prático, vamos extrair dados do IMDB. Alguns outros aplicativos possíveis para os quais você pode usar a raspagem da web são:

  • Extraia dados de classificação de filmes para criar mecanismos de recomendação de filmes.
  • Extraer datos de texto de Wikipedia y otras fuentes para crear sistemas basados ​​en PNL o entrenar modelos de aprendizado profundo para tareas como el reconocimiento de temas del texto dado.
  • Extraia dados de imagens marcadas de sites como o Google, Flickr, etc. treinar modelos de classificação de imagens.
  • Coleta de dados de sites de redes sociais como Facebook e Twitter para realizar tarefas de análise de sentimentos, mineração de opinião, etc.
  • Extraia avaliações e comentários de usuários de sites de comércio eletrônico como a Amazon, Flipkart, etc.

3. Maneiras de extrair dados

Existem várias maneiras de extrair dados da web. Algumas das formas populares são:

  • Copie e cole humanos: Esta é uma maneira lenta e eficiente de extrair dados da web. Isso envolve os próprios humanos analisando e copiando os dados para armazenamento local.
  • Correspondência de padrões de texto: Outra abordagem simples, mas poderosa, para extrair informações da web é usar as funções de correspondência de expressões regulares das linguagens de programação.. Você pode aprender mais sobre expressões regulares aqui.
  • Interface da API: Muitos sites como o Facebook, Twitter, LinkedIn, etc. fornecer APIs públicas e / ou privado que pode ser chamado usando código padrão para recuperar os dados no formato prescrito.
  • Análise DOM: Usando navegadores da web, programas podem recuperar conteúdo dinâmico gerado por scripts do lado do cliente. Também é possível analisar páginas da Web em uma árvore DOM, dependendo dos programas que podem recuperar partes dessas páginas.

Usaremos a abordagem de análise do DOM ao longo deste artigo.. E confie nos seletores CSS da página da web para encontrar os campos relevantes que contêm as informações desejadas. Mas antes de começarmos, existem alguns pré-requisitos necessários para extrair dados de qualquer site com competência.

4. Requisitos anteriores

Os pré-requisitos para realizar a raspagem da web em R se dividem em dois grupos:

  • Para começar com a raspagem da web, deve ter conhecimento prático da linguagem R. Se você está apenas começando ou quer aprimorar o básico, Eu recomendo seguir este caminho de aprendizado em R. Ao longo deste artigo, vamos usar o pacote 'rvest’ em R escrito por Hadley Wickham. Você pode acessar a documentação do pacote rvest aqui. Certifique-se de ter este pacote instalado. Se você ainda não tem este pacote, você pode seguir o código abaixo para instalá-lo.
install.packages('rvest')
  • Adicionar conhecimento de HTML e CSS será um bônus adicional. Uma das melhores fontes que encontrei para aprender HTML e CSS é Está. Observei que a maioria dos cientistas de dados não é muito forte com conhecimento técnico de HTML e CSS. Portanto, usaremos um software de código aberto chamado Selector Gadget que será mais que suficiente para qualquer pessoa fazer web scraping. Você pode acessar e baixar a extensão Selector Gadget aqui. Certifique-se de ter esta extensão instalada seguindo as instruções no site. Eu fiz o mesmo. Estou usando o Google Chrome e posso acessar a extensão na barra de extensão no canto superior direito.

ws1-8735302

Com isto, você pode selecionar as partes de qualquer site e obter as tags relevantes para acessar essa parte simplesmente clicando nessa parte do site. Observe que esta é uma maneira de aprender HTML e CSS e fazê-lo manualmente. Mas para dominar a arte de raspagem da web, Eu recomendo muito que você aprenda HTML e CSS para entender melhor e apreciar o que está acontecendo sob o capô.

4. Raspando uma página web com R

Agora, vamos começar a olhar no site do IMDb para 100 filmes mais populares lançados em 2016. Você pode acessá-los aqui.

#Loading the rvest package
library('rvest')

#Specifying the url for desired website to be scraped
url <- 'http://www.imdb.com/search/title?conde=100&release_date=2016.2016&title_type=feature'

#Reading the HTML code from the website
webpage <- read_html(url)

Agora, vamos extrair os seguintes dados deste site.

  • Classificação: A gama do filme de 1 uma 100 na lista de 100 filmes mais populares lançados em 2016.
  • Título: O título do longa-metragem.
  • Descrição: A descrição do longa-metragem.
  • Runtime: A duração do longa-metragem.
  • Gênero: O gênero do longa-metragem,
  • Classificação: A classificação IMDb do longa-metragem.
  • Metascore: O metascore no site do IMDb para o longa-metragem.
  • Votos: Votos a favor do longa-metragem.
  • Gross_Revenue_in_Thousand: Ganhos brutos de longas-metragens em milhões.
  • Diretor: O diretor principal do longa-metragem. tenha em conta que, no caso de vários diretores, vou pegar só o primeiro.
  • Ator: O ator principal do filme. tenha em conta que, no caso de vários atores, vou pegar só o primeiro.

Aqui está uma captura de tela contendo como todos esses campos estão organizados.

ws2-7967289

Paso 1: Agora, vamos começar raspando o campo Range. Para isso, usaremos o gadget seletor para obter os seletores CSS específicos que incluem as classificações. Você pode clicar na extensão em seu navegador e selecionar o campo de classificação com o cursor.

ws3-1491123

Certifique-se de que todas as classificações estão selecionadas. Você pode selecionar mais algumas seções de classificação no caso de não conseguir todas e também pode desmarque-as clicando na seção selecionada para ter certeza de que você só tem as seções destacadas que deseja raspar até lá.. .

Paso 2: Uma vez que você tenha certeza de que fez as seleções corretas, você deve copiar o seletor css correspondente que você pode ver no centro inferior.

ws4-7288393

Paso 3: Uma vez que você conhece o seletor CSS que contém as classificações, você pode usar este código R simples para obter todas as classificações:

#Using CSS selectors to scrape the rankings section
rank_data_html <- html_nodes(página web,'.text-primary')

#Converting the ranking data to text
rank_data <- html_text(rank_data_html)

#Let's have a look at the rankings
head(rank_data)

[1] "1." "2." "3." "4." "5." "6."

Paso 4: Uma vez que você tem os dados, certifique-se de que eles são vistos no formato desejado. Estou pré-transformando meus dados para convertê-lo em formato numérico.

#Pré-processamento de dados: Converting rankings to numerical
rank_data<-como.numérico(rank_data)

#Let's have another look at the rankings
head(rank_data)

[1] 1 2 3 4 5 6

Paso 5: Agora você pode limpar a seção seletor e selecionar todos os títulos. você pode inspecionar visualmente que todos os títulos são selecionados. Faça as adições e exclusões necessárias com a ajuda do seu cursor. Eu fiz a mesma coisa aqui..

ws5-2013313

Paso 6: Novamente, Eu tenho o seletor CSS correspondente para títulos: .lister-item-cabeçalho um. Usaré este seletor para raspar todos los títulos usando el siguiente código.

#Using CSS selectors to scrape the title section
title_data_html <- html_nodes(página web,'.lister-item-header a')

#Converting the title data to text
title_data <- html_text(title_data_html)

#Let's have a look at the title
head(title_data)

[1] "Cantar"          "Rio Moana"         "Luar"     "Cordilheira Hacksaw"

[5] "Passageiros"    "Trolls"

Paso 7: No seguinte código, hecho lo mismo para el raspado: Descrição, tempo de execução, Gênero sexual, qualificação, metapuntuacion, votos, ingresos brutos en mil, datos de diretor y ator.

#Using CSS selectors to scrape the description section
description_data_html <- html_nodes(página web,'.ratings-bar+ .text-muted')

#Converting the description data to text
description_data <- html_text(description_data_html)

#Let's have a look at the description data
head(description_data)

[1] "nEm uma cidade de animais humanoides, a tentativa de um empresário de teatro apressado de salvar seu teatro com uma competição de canto torna-se mais grandiosa do que ele antecipa, mesmo quando seus finalistas descobrem que suas vidas nunca mais serão as mesmas."

[2] "nNa Polinésia Antiga, quando uma terrível maldição incorrida pelo semideus Maui atinge a ilha da filha de um impetuoso Chieftain, ela responde ao chamado do Oceano para procurar o Semideus para acertar as coisas."

[3] "nUma crônica da infância, adolescência e a idade adulta florescente de um jovem, Afro-americano, gay crescendo em um bairro violento de Miami."

[4] "nWWII Médico do Exército Americano Desmond T. Doss, que serviu durante a Batalha de Okinawa, se recusa a matar pessoas, e se torna o primeiro homem na história americana a receber a Medalha de Honra sem disparar um tiro."

[5] "nA nave espacial viajando para um planeta colônia distante e transportando milhares de pessoas tem um defeito em suas câmaras de sono. Como resultado, dois passageiros são despertados 90 anos antes."

[6] "nDepois que os Bergens invadem a Vila Troll, Papoula, o Troll mais feliz já nascido, eo ramo curmudgeonly partiu em uma jornada para resgatar seus amigos.

#Pré-processamento de dados: removing 'n'
description_data<-gsub("n","",description_data)

#Let's have another look at the description data 
head(description_data)

[1] "Em uma cidade de animais humanoides, a tentativa de um empresário de teatro apressado de salvar seu teatro com uma competição de canto torna-se mais grandiosa do que ele antecipa, mesmo quando seus finalistas descobrem que suas vidas nunca mais serão as mesmas."

[2] "Na Polinésia Antiga, quando uma terrível maldição incorrida pelo semideus Maui atinge a ilha da filha de um impetuoso Chieftain, ela responde ao chamado do Oceano para procurar o Semideus para acertar as coisas."

[3] "Uma crônica da infância, adolescência e a idade adulta florescente de um jovem, Afro-americano, gay crescendo em um bairro violento de Miami."

[4] "Médico do Exército Americano da Segunda Guerra Mundial Desmond T. Doss, que serviu durante a Batalha de Okinawa, se recusa a matar pessoas, e se torna o primeiro homem na história americana a receber a Medalha de Honra sem disparar um tiro."

[5] "Uma nave espacial viajando para um planeta colônia distante e transportando milhares de pessoas tem um defeito em suas câmaras de sono. Como resultado, dois passageiros são despertados 90 anos antes."

[6] "Depois que os Bergens invadem a Vila Troll, Papoula, o Troll mais feliz já nascido, e o ramo curmudgeonly partiu em uma jornada para resgatar seus amigos."

#Using CSS selectors to scrape the Movie runtime section
runtime_data_html <- html_nodes(página web,'.text-muted .runtime')

#Converting the runtime data to text
runtime_data <- html_text(runtime_data_html)

#Let's have a look at the runtime
head(runtime_data)

[1] "108 min" "107 min" "111 min" "139 min" "116 min" "92 min"

#Pré-processamento de dados: removing mins and converting it to numerical

runtime_data<-gsub(" min","",runtime_data)
runtime_data<-como.numérico(runtime_data)

#Let's have another look at the runtime data
head(runtime_data)

[1] 1 2 3 4 5 6

#Using CSS selectors to scrape the Movie genre section
genre_data_html <- html_nodes(página web,'.gênero')

#Converting the genre data to text
genre_data <- html_text(genre_data_html)

#Let's have a look at the runtime
head(genre_data)

[1] "nAnimation, Comédia, Família "

[2] "nAnimation, Aventura, Comédia "

[3] "nDrama "

[4] "nBiografia, Drama, História "

[5] "nAdventure, Drama, Romance "

[6] "nAnimation, Aventura, Comédia "

#Pré-processamento de dados: removing n
genre_data<-gsub("n","",genre_data)

#Pré-processamento de dados: removing excess spaces
genre_data<-gsub(" ","",genre_data)

#taking only the first genre of each movie
genre_data<-gsub(",.*","",genre_data)

#Convering each genre from text to factor
genre_data<-as.fator(genre_data)

#Let's have another look at the genre data
head(genre_data)

[1] Animação animação drama de aventura animação aventura

10 Níveis: Action Adventure Animation Biography Comedy Crime Drama ... Thriller

#Using CSS selectors to scrape the IMDB rating section
rating_data_html <- html_nodes(página web,'.ratings-imdb-rating forte')

#Converting the ratings data to text
rating_data <- html_text(rating_data_html)

#Let's have a look at the ratings
head(rating_data)

[1] "7.2" "7.7" "7.6" "8.2" "7.0" "6.5"

#Pré-processamento de dados: converting ratings to numerical
rating_data<-como.numérico(rating_data)

#Let's have another look at the ratings data
head(rating_data)

[1] 7.2 7.7 7.6 8.2 7.0 6.5

#Using CSS selectors to scrape the votes section
votes_data_html <- html_nodes(página web,'.num_votes-visível:nth-criança(2)')

#Converting the votes data to text
votes_data <- html_text(votes_data_html)

#Let's have a look at the votes data
head(votes_data)

[1] "40,603"  "91,333"  "112,609" "177,229" "148,467" "32,497"

#Pré-processamento de dados: removing commas
votes_data<-gsub(",","",votes_data)

#Pré-processamento de dados: converting votes to numerical
votes_data<-como.numérico(votes_data)

#Let's have another look at the votes data
head(votes_data)

[1]  40603  91333 112609 177229 148467  32497

#Using CSS selectors to scrape the directors section
directors_data_html <- html_nodes(página web,'.text-muted+ p a:nth-criança(1)')

#Converting the directors data to text
directors_data <- html_text(directors_data_html)

#Let's have a look at the directors data
head(directors_data)

[1] "Christophe Lourdelet" "Ron Clements"         "Barry Jenkins"

[4] "Mel Gibson"           "Morten Tyldum"        "Walt Dohrn"

#Pré-processamento de dados: converting directors data into factors
directors_data<-as.fator(directors_data)

#Using CSS selectors to scrape the actors section
actors_data_html <- html_nodes(página web,'.lister-item-content .ghost+ a')

#Converting the gross actors data to text
actors_data <- html_text(actors_data_html)

#Let's have a look at the actors data
head(actors_data)

[1] "Matthew McConaughey" "Auli'i Cravalho"     "Mahershala Ali"

[4] "Andrew Garfield"     "Jennifer Lawrence"   "Anna Kendrick"

#Pré-processamento de dados: converting actors data into factors
actors_data<-as.fator(actors_data)

Pero quiero que siga de cerca lo que sucede cuando hago lo mismo con los datos de Metascore.

#Using CSS selectors to scrape the metascore section
metascore_data_html <- html_nodes(página web,'.metascore')

#Converting the runtime data to text
metascore_data <- html_text(metascore_data_html)

#Let's have a look at the metascore 
data head(metascore_data)

[1] "59        " "81        " "99        " "71        " "41        "

[6] "56        "

#Pré-processamento de dados: removing extra space in metascore
metascore_data<-gsub(" ","",metascore_data)

#Lets check the length of metascore data
length(metascore_data)

[1] 96

Paso 8: O comprimento dos dados metascore é 96 enquanto estamos raspando os dados de 100 Filmes. A razão pela qual isso aconteceu é que há 4 filmes que não têm os campos Metascore correspondentes.

ws6-2924905

Paso 9: É uma situação prática que pode surgir ao raspar qualquer site. Infelizmente, se simplesmente adicionar NA ao mais recente 4 ingressos, NA será designado como Metascore para filmes 96 uma 100, enquanto, na verdade,, dados perdidos para alguns outros filmes. Após uma inspeção visual, Descobri que metascore estava faltando para filmes 39, 73, 80 e 89. Eu escrevi o seguinte recurso para corrigir este problema.

para (i em c(39,73,80,89)){

uma<-metascore_data[1:(i-1)]

b<-metascore_data[eu:comprimento(metascore_data)]

metascore_data<-acrescentar(uma,Lista("N / D"))

metascore_data<-acrescentar(metascore_data,b)

}

#Pré-processamento de dados: converting metascore to numerical
metascore_data<-como.numérico(metascore_data)

#Let's have another look at length of the metascore data

length(metascore_data)

[1] 100

#Let's look at summary statistics
summary(metascore_data)

Mín.. 1st Qu.  Média Mediana 3º Qu.    Máx..    Na's

23.00   47.00   60.00   60.22   74.00   99.00       4

Paso 10: Lo mismo sucede con la variável Bruto que representa los ingresos brutos de esa película en millones. Ele usado la misma solución para trabajar a mi manera:

#Using CSS selectors to scrape the gross revenue section
gross_data_html <- html_nodes(página web,'.ghost~ .text-muted+ span')

#Converting the gross revenue data to text
gross_data <- html_text(gross_data_html)

#Let's have a look at the votes data
head(gross_data)

[1] "$269.36M" "$248.04M" "$27.50M"  "$67.12M"  "$99.47M"  "$153.67M"

#Pré-processamento de dados: removing '$' and 'M' signs
gross_data<-gsub("M","",gross_data)

gross_data<-Subsequência(gross_data,2,6)

#Let's check the length of gross data
length(gross_data)

[1] 86

#Filling missing entries with NA
for (i em c(17,39,49,52,57,64,66,73,76,77,80,87,88,89)){

uma<-gross_data[1:(i-1)]

b<-gross_data[eu:comprimento(gross_data)]

gross_data<-acrescentar(uma,Lista("N / D"))

gross_data<-acrescentar(gross_data,b)

}

#Pré-processamento de dados: converting gross to numerical
gross_data<-como.numérico(gross_data)

#Let's have another look at the length of gross data
length(gross_data)

[1] 100

resumo(gross_data)

Mín.. 1st Qu.  Média Mediana 3º Qu.    Máx..    Na's

0.08   15.52   54.69   96.91  119.50  530.70      14

Paso 11: Ahora hemos eliminado con éxito las 11 termos de las 100 filmes mais populares lançados em 2016. Combinémoslas para crear un marco de datos e inspeccionar su estructura.

#Combining all the lists to form a data frame
movies_df<-quadro de dados(Classificação = rank_data, Título = title_data,

Descrição = description_data, Tempo de execução = runtime_data,

Gênero = genre_data, Classificação = rating_data,

Metascore = metascore_data, Votos = votes_data,                                                             Gross_Earning_in_Mil = gross_data,

Diretor = directors_data, Ator = actors_data)

#Structure of the data frame

str(movies_df)

'data.frame':            100 obs. do  11 variáveis:

$ Classificação                : num  1 2 3 4 5 6 7 8 9 10 ...

$ Título               : Fator c/ 99 Níveis "10 Cloverfield Lane",..: 66 53 54 32 58 93 8 43 97 7 ...

$ Descrição         : Fator c/ 100 Níveis "19-billy lynn de ano de idade é trazido para casa para uma turnê de vitória depois de uma batalha angustiante iraque. Através de flashbacks o filme mostra o que"| __truncated__,..: 57 59 3 100 21 33 90 14 13 97 ...

$ Tempo de execução             : num  108 107 111 139 116 92 115 128 111 116 ...

$ Gênero               : Fator c/ 10 Níveis "Ação","Aventura",..: 3 3 7 4 2 3 1 5 5 7 ...

$ Classificação              : num  7.2 7.7 7.6 8.2 7 6.5 6.1 8.4 6.3 8 ...

$ Metascore           : num  59 81 99 71 41 56 36 93 39 81 ...

$ Votos               : num  40603 91333 112609 177229 148467 ...

$ Gross_Earning_in_Mil: num  269.3 248 27.5 67.1 99.5 ...

$ Diretor            : Fator c/ 98 Níveis "Andrew Stanton",..: 17 80 9 64 67 95 56 19 49 28 ...

$ Ator               : Fator c/ 86 Níveis "Aaron Eckhart",..: 59 7 56 5 42 6 64 71 86 3 ...

Você agora raspou com sucesso o site do IMDb para o 100 filmes mais populares lançados em 2016.

6. Analise dados extraídos da Web

Uma vez que você tem os dados, pode executar várias tarefas, como analisar os dados, fazer inferências a partir deles, treinar modelos de aprendizado de máquina nesses dados, etc. Continuei a criar uma visualização interessante a partir dos dados que acabamos de extrair. Siga as visualizações e responda às perguntas abaixo. Poste suas respostas na seção de comentários abaixo.

biblioteca('ggplot2')

qplot(dados = filmes_df,Tempo de execução,preencher = Gênero,bins = 30)

ws7-7852055

Pergunta 1: De acordo com os dados acima, qual filme de qual gênero teve o maior tempo de execução?

ggplot(movies_df,aes(x=Tempo de execução,y=Classificação))+
geom_point(aes(tamanho=votos,col=Gênero))

ws8-2948438

Pergunta 2: De acordo com os dados acima, em tempo de execução 130-160 minutos, qual gênero tem mais votos?

ggplot(movies_df,aes(x=Tempo de execução,y=Gross_Earning_in_Mil))+
geom_point(aes(tamanho=Classificação,col=Gênero))

ws9-4512146

Pergunta 3: De acordo com os dados acima, em todos os gêneros, qual gênero tem os maiores ganhos brutos médios em tempo de execução de 100 uma 120.

Notas finais

Eu acho que este artigo teria lhe dado uma compreensão completa do web scraping em R. Agora, você também tem uma ideia clara dos problemas que pode encontrar e como pode corrigi-los. Como a maioria dos dados na web está presente em um formato não estruturado, web scraping é uma habilidade muito útil para qualquer cientista de dados.

O que mais, você pode postar as respostas para as três perguntas acima na seção de comentários abaixo. Você gostou de ler este artigo? Compartilhe suas opiniões comigo. Se você tiver alguma dúvida / pergunta, fique a vontade para enviar abaixo.

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.