html - R:如何抓取 {{variable}} 容器
问题描述
当webscraping时,我得到:{{price}}
. 网络浏览器显示价格 S/1800.00(某个数字),查看源代码是您看到{{price}}
.
发生这种情况precio.tarjeta
,我正确地得到了所有其他变量。
代码:
library(rvest)
library(purrr)
library(tidyverse)
urls <- list("https://www.oechsle.pe/tecnologia/televisores/?&optionOrderBy=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&O=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&page=1",
"https://www.oechsle.pe/tecnologia/televisores/?&optionOrderBy=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&O=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&page=2")
h <- urls %>% map(read_html) # scrape once, parse as necessary
df <- map_dfr(h %>%
map(~ .x %>%
html_nodes("div.product")), ~
data.frame(
periodo = lubridate::year(Sys.Date()),
fecha = Sys.Date(),
ecommerce = "oeschle",
marca = .x %>% html_node(".brand") %>% html_text(),
producto = .x %>% html_node(".prod-name") %>% html_text(),
precio.antes = .x %>% html_node('.ListPrice') %>% html_text(),
precio.actual = .x %>% html_node('.BestPrice') %>% html_text(),
precio.tarjeta = .x %>% html_node('.tOhPrice') %>% html_text()
))
更新 1:
我注意到产品会重复自己,即存在重复的产品,即使它们是第 1 页和第 2 页的浏览器中的不同产品。
为什么?
解决方案
如何抓取 {{variable}} 容器
这里的答案是花一些时间通过研究页面源、调用的各种 JS 脚本和网络选项卡来了解页面如何动态更新自身。我想你可以跳过搜索网络标签并希望在那里找到你想要的东西。但是,在学习一些有关模板、内容提供者、动态页面如何更新等方面的知识时,您会输掉......
您看到的是 JavaScript 模板。内容提供者 VTEX 提供模板和各种脚本,这些脚本驱动这些“占位符”的实际值更新,例如 {{price}} 和 {{percent}}。
为了获得您想要的值,这里需要注意的是,有一个调用 API 端点,带有来自页面的产品 id,并且返回的 JSON 包含您所追求的内容。您可以通过动态提取 id 并将相同的 GET 请求发送到 API 来复制此请求。
借助辅助函数,您可以提取折扣,然后从互联网价格中减去。虽然从 API 调用返回了各种其他价格(以及更多信息),但我决定从初始 GET 请求中提取其他价格。
这是一个 url 的示例:
library(rvest)
library(tidyverse)
library(jsonlite)
get_oh_price <- function(item) {
var <- item$items[[1]]$sellers[[1]]$commertialOffer$Teasers
oh_discount <- 100 * ifelse(length(var) == 0, 0, var[[1]]$`<Effects>k__BackingField`$`<Parameters>k__BackingField`[[2]]$`<Value>k__BackingField`) |> as.numeric()
return(tibble(id = item$productId, oh_discount))
}
api_prefix <- "https://www.oechsle.pe/api/catalog_system/pub/products/search?fq="
api_suffix <- "&_from=0&_to=49&sc=1"
url <- "https://www.oechsle.pe/tecnologia/televisores/?&optionOrderBy=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&O=OrderByScoreDESC&optionOrderBy=OrderByScoreDESC&page=1"
page <- read_html(url)
listings <- page |> html_elements("[id^=ResultItems_] li[layout]")
df <- map_dfr(listings, ~
data.frame(
id = .x |> html_element(".product") |> html_attr("data-id"),
name = .x |> html_element(".product") |> html_attr("data-name"),
brand = .x |> html_element(".product") |> html_attr("data-brand"),
category = .x |> html_element(".product") |> html_attr("data-cat"),
link = .x |> html_element(".product") |> html_attr("data-link"),
instock = .x |> html_element(".product") |> html_attr("data-stock"),
antes = .x |> html_element(".ListPrice") |> html_text() |> str_replace_all("S/.\\s+|,|\\.", "") |> as.numeric(),
internet = .x |> html_element(".BestPrice") |> html_text() |> str_replace_all("S/.\\s+|,|\\.", "") |> as.numeric(),
currency = "S/"
))
api_request <- paste0(api_prefix, paste(sprintf("productId:%s,", df$id), sep = "", collapse = ""), api_suffix)
product_data <- jsonlite::read_json(api_request)
discount_df <- map_dfr(product_data, get_oh_price)
df <- df |> inner_join(discount_df, by = "id")
df$oh_price <- map2_dbl(df$internet, df$oh_discount, .f = ~ ifelse(.y == 0, NA_integer_, .x - .y))
推荐阅读
- database - Heroku Postgres:最大的work_mem设置出现内存不足错误
- git - Git拉错误-\ store:store:找不到命令
- c - 如果我退出第一个 printf,为什么这个 C 代码会失败?
- html - 隐藏溢出不禁用滚动条
- reactjs - 使用浏览器调整构建结果选项卡贡献的大小
- javascript - JavaScript 在 setInterval 调用的函数中使用 screen.width 或 screen.availWidth 时未获得更新的值
- sql - Azure Synapse 文件无法打开错误
- date - 多日活动的 RRULE
- php - 对层次较深的数据进行分组时如何处理 SQL 聚合函数
- python - 循环遍历列表并从头开始