有没有办法在 R 中有选择地收集网络数据?

Is there a way to collect web data selectively in R?

我正在尝试从德国乐天网站抓取数据。 Rakuten 公司是总部位于日本的世界知名企业,通过 Internet 销售各种商品。问题是他们针对不同的国家采用不同的市场策略。例如,在美国,人们在支付所谓的订阅费之前无法获得产品。在德国则不同,在那里可以立即了解产品和价格。因此,Rakuten 的链接似乎带有地理标记,即如果从另一个目的地登录,则看不到内容。此序言对于尝试按照我的步骤操作并遇到连接错误的每个人都很重要。
好的,话虽如此,我想读取数据并将其保存到数据框中。

这是我的初始代码:

library(rvest)
library(purrr)
library(dplyr)     

rakuten <- "https://www.rakuten.de/suchen/kitchenAid?category=0"
ra_html <- read_html(rakuten)

title <- html_nodes(ra_html, ".vw-productCard .name") 
price <- html_nodes(ra_html, ".vw-productCard .price .actual")
discount <- html_nodes(ra_html, ".vw-productCard .thumb .discount .text") 

如你所见,我想抓取产品说明(标题object)、价格(价格object)和折扣可用性(折扣object)(如果有的话) .他们销售的每种产品总是有描述和价格(我正在查看 KitchenAid 的价格),但 折扣很少发生

然后我解析数据:

urlrakuten <- sprintf("https://www.rakuten.de/suchen/kitchenAid?category=0", 1:10)

#define empty data frame to store all data
alllistings <- data.frame()

for (i in urlrakuten){
  
  print(i)
  #read the page just once
  page <- read_html(i)
      
  # parse titles
 title <- page%>%html_nodes('.vw-productCard .name') %>% html_text()
 
  # parse prices
  price <- page %>% html_nodes('.vw-productCard .price .actual') %>% html_text()
  
  # parse discounts
  discount <- page %>% html_nodes('.vw-productCard .thumb .discount .text') %>%  html_text()

  #create temporary dataframe to store data from this loop
  tempdf <- data.frame(title, price, discount) 
  
  #combine temp with all data
  alllistings <- rbind(alllistings, tempdf)
}

前两个 object 效果非常好,但最后一个(折扣)效果不佳。第一页上只有四个折扣,R 将它们全部刮掉,然后用这四个值的重复填充其余行,请参阅我的输出:

我确实遗漏了一些东西,但我不知道如何修复它。我想要相同的输出,第三列值组织到它们所属的行,其余的只填充 NAs。

按照本题攻略:。由于并非每个产品都有折扣,因此使用 html_nodes() 函数会导致您看到的问题,因为它仅 return 找到的节点。
因此解决方案是生成一个向量所有产品的父节点,然后用 html_node() 解析每个父节点。 html_node() 函数将始终 return 一个值,即使它只是 NA。

另请注意:我正在使用 lapply 函数来 return 数据帧列表(每个页面一个)并将它们同时绑定在一起。与循环内绑定的增量方法相比,这是一个显着的性能改进。

library(rvest)
library(dplyr)
library(tibble)

readpage <- function(url){
   #read the page once
   page <-read_html(url)
   
   #parse out the parent nodes (the product)
   products <- page %>% html_nodes( "li.vw-productCard")
   
   #Now extract one piece of imformation per parent
   #title
   title <- products%>%html_node('.name') %>% html_text() 
   
   # parse prices
   price <- products %>% html_node('.price .actual') %>% html_text() %>% trimws()
  
   # parse discounts (html_node will return NA if no discount is available)
   discount <- products %>% html_node('.thumb .discount .text') %>%  html_text()
   
   #return a tibble/data,frame
   tibble(title, price, discount, url)
}

listofurls <- paste0("https://www.rakuten.de/suchen/kitchenAid?category=0&page=", 1:10)

dfs <- lapply(listofurls, function(url){ readpage(url)})
finalanswer <- bind_rows(dfs)