RVEST软件包似乎以随机顺序收集数据

问题描述

我有以下问题。

我正试图从Booking网站上收集数据(仅对我自己,以便了解rvest软件包的功能)。一切都很好,程序包似乎可以收集我想要的东西,并将所有内容放入表(数据框)中。 这是我的代码

library(rvest)
library(lubridate)
library(tidyverse)

page_booking <- c("https://www.booking.com/searchresults.html?aid=397594&label=gog235jc-1FCAEoggI46AdIM1gDaDuIAQGYAQe4ARfIAQzYAQHoAQH4AQyIAgGoAgO4Atap6PoFwAIB0gIkY2RhYmM2NTUtMDRkNS00ODY1LWE3MDYtNzQ1ZmRmNjY3NWY52AIG4AIB&sid=409e05f0cfc7a9e98de21dc3e633dbd6&tmpl=searchresults&ac_click_type=b&ac_position=0&checkin_month=9&checkin_monthday=10&checkin_year=2020&checkout_month=9&checkout_monthday=17&checkout_year=2020&class_interval=1&dest_id=197&dest_type=country&from_sf=1&group_adults=2&group_children=0&label_click=undef&no_rooms=1&offset=0&raw_dest_type=country&room1=A%2CA&sb_price_type=total&search_selected=1&shw_aparth=1&slp_r_match=0&src=index&src_elem=sb&srpvid=eb0e56a23d6c0004&ss=Spanien&ss_raw=spanien&ssb=empty&top_ufis=1&selected_currency=USD&changed_currency=1&top_currency=1&nflt=") %>%
  paste0(1:60) %>%
  paste0(c("?ie=UTF8&pageNumber=")) %>%
  paste0(1:60) %>%
  paste0(c("&pageSize=10&sortBy=recent"))

因此,在此数据块中,我首先手动向Booking搜索引擎提供了我所选择的国家(西班牙),我感兴趣的日期(只是任意间隔)和人员(我在这里使用认值)。

然后,我添加以下代码以选择所需的属性

read_hotel <- function(url){  # collecting hotel names
  ho <- read_html(url)
  headline <- ho %>%
    html_nodes("span.sr-hotel__name") %>%  # the node I want to read
    html_text() %>%
    as_tibble()
} 

hotels <- map_dfr(page_booking,read_hotel)

read_pr <- function(url){    # collecting price tags
  pr <- read_html(url)
  full_pr <- pr %>%
    html_nodes("div.bui-price-display__value") %>% #the node I want to read
   html_text() %>%
    as_tibble()
}

fullprice <- map_dfr(page_booking,read_pr)

...并最终将整个数据保存在数据框中:

dfr <- tibble(hotels = hotels,price_fact =  fullprice)

我收集了更多参数,但这无关紧要。然后创建1500行和两列的最终数据框。但是问题是第二列中的数据与第一列中的数据不对应。这真的很奇怪,使我的数据框变得毫无用处。 我真的不了解该程序包如何在后台运行,以及为什么会这样运行。我还注意了数据框第一栏中的第一行(酒店名称)与我在网站上看到的第一批酒店不对应。因此,rvest软件包使用的似乎是不同的搜索/排序/过滤条件。 您能否解释一下在RVest节点希望期间发生的过程? 我真的很感谢至少有一些解释,只是为了更好地了解我们使用的工具。

解决方法

您不应像这样单独刮擦酒店的名称和价格。您应该做的是获取商品(酒店)的所有节点,然后相对刮取每个酒店的名称和价格。使用这种方法,您就不会弄乱订单。

library(rvest)
library(purrr)
page_booking <- c("https://www.booking.com/searchresults.html?aid=397594&label=gog235jc-1FCAEoggI46AdIM1gDaDuIAQGYAQe4ARfIAQzYAQHoAQH4AQyIAgGoAgO4Atap6PoFwAIB0gIkY2RhYmM2NTUtMDRkNS00ODY1LWE3MDYtNzQ1ZmRmNjY3NWY52AIG4AIB&sid=409e05f0cfc7a9e98de21dc3e633dbd6&tmpl=searchresults&ac_click_type=b&ac_position=0&checkin_month=9&checkin_monthday=10&checkin_year=2020&checkout_month=9&checkout_monthday=17&checkout_year=2020&class_interval=1&dest_id=197&dest_type=country&from_sf=1&group_adults=2&group_children=0&label_click=undef&no_rooms=1&offset=0&raw_dest_type=country&room1=A%2CA&sb_price_type=total&search_selected=1&shw_aparth=1&slp_r_match=0&src=index&src_elem=sb&srpvid=eb0e56a23d6c0004&ss=Spanien&ss_raw=spanien&ssb=empty&top_ufis=1&selected_currency=USD&changed_currency=1&top_currency=1&nflt=") %>%
  paste0(1:60) %>%
  paste0(c("?ie=UTF8&pageNumber=")) %>%
  paste0(1:60) %>%
  paste0(c("&pageSize=10&sortBy=recent"))


hotels <- 
  map_dfr(
    page_booking,function(url) {
      pg <- read_html(url)
      items <- pg %>%
        html_nodes(".sr_item")
      map_dfr(
        items,function(item) {
          data.frame(
            hotel = item %>% html_node(xpath = "./descendant::*[contains(@class,'sr-hotel__name')]") %>% html_text(trim = T),price = item %>% html_node(xpath = "./descendant::*[contains(@class,'bui-price-display__value')]") %>% html_text(trim = T)
          )
        }
      )
    }
  )

(以XPath语法开头的点表示当前节点,即酒店项目。)

更新: 更新我认为更快但仍然可以完成的代码:

hotels <-
  map_dfr(
    page_booking,function(url) {
      pg <- read_html(url)
      items <- pg %>%
        html_nodes(".sr_item")
      data.frame(
        hotel = items %>% html_node(xpath = "./descendant::*[contains(@class,price = items %>% html_node(xpath = "./descendant::*[contains(@class,'bui-price-display__value')]") %>% html_text(trim = T)
      )
    }
  )