【问题标题】:R: webscraping data elements returns NAR:网络抓取数据元素返回 NA
【发布时间】:2021-09-16 01:01:53
【问题描述】:

我对价格不满意。我以为我正确使用了html_attr() 函数,但显然我遗漏了一些东西。

我从这个 HTML 中得到了 marca 和 product 字段,但没有得到价格:

<li data-internet-price="2,899" class="jsx-3342506598 price-0">    
  <div data-variant="DESKTOP_LIST" class="jsx-3342506598 cmr-icon-container"> 
    <span id="" class="copy10 primary high jsx-2612542277 normal     ">
S/  2,899 (Oferta) </span>
  </div>
</li>

我需要捕获 data-internet-price

的内容

代码:

library(rvest)
library(purrr)
library(tidyverse)

urls <- list("https://www.falabella.com.pe/falabella-pe/category/cat210477/TV-Televisores?page=1",
             "https://www.falabella.com.pe/falabella-pe/category/cat210477/TV-Televisores?page=2")

h <- urls %>% map(read_html) # scrape once, parse as necessary




df <- map_dfr(h %>%
                map(~ .x %>%
                      html_nodes("div.search-results-list")), ~
                data.frame(
                  periodo = lubridate::year(Sys.Date()),
                  fecha = Sys.Date(),
                  ecommerce = "falabella",
                  marca = .x %>% html_node(".pod-title") %>% html_text(),
                  producto = .x %>% html_node(".pod-subTitle") %>% html_text(),
                  precio.antes = .x %>% html_node('.prices') %>% html_attr("data-internet-price"),
                  precio.actual = .x %>% html_node('.prices') %>% html_attr("data-normal-price")
                ))

【问题讨论】:

    标签: html r web-scraping purrr


    【解决方案1】:

    如果您在与 html 关联的页面上检查 html,如上所示,这些属性对于您选择的节点不存在,因此 N/A 即您实际上是在选择没有然后尝试提取的属性。 html_attr() 在您从左侧管道的当前节点级别工作。

    你想在 DOM 中走得更远,或者通过在现有的 .prices 类 css 选择器中添加一个后代组合器和另一个选择器,例如.prices [data-internet-price],或者直接选择具有这些属性的子节点:

    precio.antes = .x %>% html_node('[data-internet-price]') %>% html_attr("data-internet-price"),
    precio.actual = .x %>% html_node('[data-normal-price]') %>% html_attr("data-normal-price")
    

    编辑:

    看起来,要获取所有列表,您需要定位一个 script 标记,其中在浏览器中运行的 JavaScript 会拉取额外的(每页 >12 个)列表。然后,您可以将检索到的 JavaScript 对象解析为 JSON,并编写一些自定义代码来提取您想要的项目;同时处理缺失值(我通过对每个可能价格的默认 DataFrame 房屋 NA 进行右连接来完成)。

    您可能希望对最后一列进行重命名。我已将所有 4 个价格列与它们在页面源中给出的名称一起保留。


    library(rvest)
    library(purrr)
    library(tidyverse)
    
    urls <- list(
      "https://www.falabella.com.pe/falabella-pe/category/cat210477/TV-Televisores?page=1",
      "https://www.falabella.com.pe/falabella-pe/category/cat210477/TV-Televisores?page=2"
    )
    
    h <- urls |> map(read_html) # scrape once, parse as necessary
    
    default_df <- data.frame(type = c("cmrPrice", "internetPrice", "normalPrice", "eventPrice"), price = c(NA, NA, NA, NA))
    
    df <- map_dfr(h |>
      map(~ .x |>
        html_node("#__NEXT_DATA__") |>
        html_text() |>
        jsonlite::parse_json() %>%
        {
          .$props$pageProps$results
        }) |> unlist(recursive = F), ~
    
    data.frame(
      periodo = lubridate::year(Sys.Date()),
      fecha = Sys.Date(),
      ecommerce = "falabella",
      marca = .x$brand,
      producto = .x$displayName,
      temp = .x$prices |> map_dfr(~ data.frame(type = .x$type, price = .x$price[[1]])) |>
        right_join(default_df, by = "type", suffix = c("", ".y")) |> select(type, price) |>
        pivot_wider(names_from = type, values_from = price)
    )) |>
      select_all(~ str_replace(., "temp.", ""))
    

    【讨论】:

    • 谢谢。请问你,我的代码有这 2 页的 96 个元素吗?我只得到 24 个。但是手动计算我发现每个页面有 48 个元素。
    • 如果没有 JS 在浏览器中运行,与 rvest 一样,在 html 中为该选择器返回的第 1 页有 12 个列表。
    • 我想我需要使用 RSelenium。我遇到了另一个问题,我被它困住了,你可以检查一下吗? stackoverflow.com/questions/69186034/…
    • 你不需要这样做。您只需要从脚本标签中提取。我会更新答案。
    • 泰。引起我注意的是,您使用我所说的属性作为节点:html_node('[data-internet-price]'),对我来说,该节点将是 &lt;li&gt;。那什么是节点?在 rvest pckg 信息页面中找不到足够的信息。另外,请参阅我使用 RSelenium 的其他问题。
    猜你喜欢
    • 2021-12-06
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2019-02-13
    相关资源
    最近更新 更多