Какой была бы наилучшая практика для объединения дополнительных переменных с данными на основе конкретной информации о строке при веб-очистке в R с использованием ‘rvest’?

#r #web-scraping #data.table #apply #rvest

#r #веб-очистка #data.table #применить #rvest

Вопрос:

В настоящее время я просматриваю веб-сайт IMDB для извлечения данных фильма.

Я хотел бы знать, как вы решите эту проблему.

 library(tidyverse)
library(data.table)
library(rvest)
library(janitor)

#top rated movies website 
url <- 'https://www.imdb.com/chart/top/?ref_=nv_mv_250'

# extract the title of the movies using rvest

titles <- url %>%
  read_html() %>%
  html_nodes(' .titleColumn a') %>%
  html_text() %>%
  as.data.table() %>%
  setnames(. ,old = colnames(.), new='title') 

# extract links to each of the titles, this will be the reference 

links <- url %>%
  read_html() %>%
  html_nodes('.titleColumn a') %>%
  html_attr('href') %>%
  as.data.table() %>%
  setnames(. ,old = colnames(.), new='links') 

# creating a DT with the data

movies <- cbind(titles,links)

  

У меня будут фильмы DT с заголовком и ссылками в виде столбцов.

Теперь я хотел бы извлечь дополнительные данные каждого фильма, используя ссылки

Я продолжу использовать первую строку в качестве примера.

 
#the first link in movies  

link <- 'https://www.imdb.com/title/tt0111161/?pf_rd_m=A2FGELUUNOQJNLamp;pf_rd_p=e31d89dd-322d-4646-8962-327b42fe94b1amp;pf_rd_r=NJ52X0MM1V9FKSPBT46Gamp;pf_rd_s=center-1amp;pf_rd_t=15506amp;pf_rd_i=topamp;ref_=chttp_tt_1'

# selector for budget data (this will not change)

select <- '.txt-block:nth-child(15) , .txt-block:nth-child(14) , #titleDetails .txt-block:nth-child(13) , #titleDetails .txt-block:nth-child(12)'


# get budget data

budget <- link %>%
  read_html() %>%
  html_nodes(select) %>%
  html_text() %>%
  gsub('\n','',.) %>%
  str_split(.,'\:')%>%
  as.data.table() %>%
  janitor::row_to_names(row_number = 1) %>%
  setnames(.,old=colnames(.),new= tolower(gsub(' ','_' , str_trim(colnames(.)))))

budget[,(colnames(budget))] <- lapply(budget,function(x) str_extract_all(x, "(\$) *([0-9,] )"))

  

Теперь у меня есть таблица 1×4 с информацией о бюджете

Я хотел бы получить данные для каждой ссылки на фильмы и объединить их в DT, чтобы получить окончательный DT с 6 столбцами; ‘title’, ‘link’ четыре переменные бюджета. Я пытался создать функцию, которая включает в себя код для получения бюджетных данных, используя ссылку на каждую строку в качестве параметра и используя ‘lapply’, я не думаю, что это правильный подход.

Я хотел бы посмотреть, есть ли у вас эффективное решение этой проблемы.

Большое спасибо за вашу помощь.

Ответ №1:

Я думаю, это решило бы вашу проблему:

 # selector for budget data (this will not change)
select <- '.txt-block:nth-child(15) , .txt-block:nth-child(14) , #titleDetails .txt-block:nth-child(13) , #titleDetails .txt-block:nth-child(12)'

# get budget data
## As function
get_budget = function(link,select){
budget <- link %>%
  read_html() %>%
  html_nodes(select) %>%
  html_text() %>%
  gsub('\n','',.) %>%
  str_split(.,'\:')%>%
  as.data.table() %>%
  janitor::row_to_names(row_number = 1) %>%
  setnames(.,old=colnames(.),new= tolower(gsub(' ','_' , str_trim(colnames(.)))))

budget[,(colnames(budget))] <- lapply(budget,function(x) str_extract_all(x, "(\$) *([0-9,] )"))
return(budget)
}

#As your code is slow I'll subset movies to have 10 rows:
movies = movies[1:10,]
tmp = 
lapply(movies[, links], function(x) 
  get_budget(link = paste0("https://www.imdb.com/",x),select=select )) %>% 
  rbindlist(., fill = T)

movies = cbind(movies, tmp)
  

И ваш результат будет выглядеть так: movies_result

Наконец, я думаю, что этот небольшой совет сделает ваш код более крутым:

  • setnames не требуется . from magrittr ; он автоматически понимает ваш тип кода.
  • По возможности избегайте использования setnames(. ,old = colnames(.), new='links') . В вашем случае это просто необходимо setnames('links') , поскольку вы переименовываете все свои переменные.
  • setnames(dt,old = oldnames, new=newnames) необходимо только тогда, когда oldnames не равно names (dt).
  • Поскольку DT это еще R одна популярная библиотека, совершенно не связанная с data.table , я думаю, лучше ссылаться на data.table как на то, что есть data.table .

Комментарии:

1. Большое спасибо! Ваши предложения были полезны!