首页 > 解决方案 > 无法使用 rvest 刮掉所有行

问题描述

我的目标是从 bluenile.com 抓取所有这些钻石数据。我有一些似乎正在这样做的代码,但它只抓取前 61 行。

顺便说一句,我正在使用“ SelectorGadget ”chrome 插件来获取 CSS 选择器。如果我向下滚动一点,突出显示停止。跟网站有关系吗?

library('rvest')

le_url <- "https://www.bluenile.com/diamonds/round-cut?track=DiaSearchRDmodrn"
webpage <- read_html(le_url)

shape_data_html <- html_nodes(webpage,'.shape')
price_data_html <- html_nodes(webpage,'.price')
carat_data_html <- html_nodes(webpage,'.carat')
cut_data_html <- html_nodes(webpage,'.cut')
color_data_html <- html_nodes(webpage,'.color')
clarity_data_html <- html_nodes(webpage,'.clarity')

#Converting data to text
shape_data <- html_text(shape_data_html)
price_data <- html_text(price_data_html)
carat_data <- html_text(carat_data_html)
cut_data <- html_text(cut_data_html)
color_data <- html_text(color_data_html)
clarity_data <- html_text(clarity_data_html)

# make a data.frame
le_mat <- cbind(shape_data, price_data, carat_data, cut_data, color_data, clarity_data)
le_df <- le_mat[-1,]
colnames(le_df) <- le_mat[1,]

标签: cssrweb-scrapingcss-selectorsrvest

解决方案


向下滚动页面时,通过 API 调用动态添加数据。API 调用有一个查询字符串,允许您指定startIndex(起始行)和每页的结果数 ( pageSize)。每页最大结果似乎是 1000。返回是 json,您可以从中提取所需的所有信息,包括总行数;通过 的键访问countRaw。因此,您可以请求最初的 1000,解析出总行数,countRaw然后执行循环,调整行startIndex参数,直到获得所有结果。

您可以使用 json 解析器,例如 jsonlite 来处理 json 响应。

前 1000 个结果的示例 API 端点调用:

https://www.bluenile.com/api/public/diamond-search-grid/v2?startIndex=0&pageSize=1000&_=1562612289615&sortDirection=asc&sortColumn=default&shape=RD&hasVisualization=true&isFiltersExpanded=false&astorFilterActive=false&country=USA&language=en-us¤cy=USD&productSet= BN&skus=

library(jsonlite)

url <- 'https://www.bluenile.com/api/public/diamond-search-grid/v2?startIndex=0&pageSize=1000&_=1562612289615&sortDirection=asc&sortColumn=default&shape=RD&hasVisualization=true&isFiltersExpanded=false&astorFilterActive=false&country=USA&language=en-us&currency=USD&productSet=BN&skus='
r <-  jsonlite::fromJSON(url)
print(r$countRaw)

您会从每次调用中获得一个包含 8 个元素的列表。r$results是一个包含主要兴趣信息的数据框。

部分回复:

在此处输入图像描述


鉴于指示的结果计数,我期望我可以做类似的事情(记住我有限的 R 经验):

total <- r$countRaw
url2 <- 'https://www.bluenile.com/api/public/diamond-search-grid/v2?startIndex=placeholder&pageSize=1000&_=1562612289615&sortDirection=asc&sortColumn=default&shape=RD&hasVisualization=true&isFiltersExpanded=false&astorFilterActive=false&country=USA&language=en-us&currency=USD&productSet=BN&skus='
if(total > 1000){
  for(i in seq(1000, total + 1, by = 1000)){
    newUrl <- gsub("placeholder", i , url2)
    newdf <- jsonlite::fromJSON(newUrl)$results
    # do something with df e.g. merge
  }
}

但是,似乎只有前两个调用的结果,即上面显示的初始df结果r$results,然后:

url2 <- 'https://www.bluenile.com/api/public/diamond-search-grid/v2?startIndex=1000&pageSize=1000&_=1562612289615&sortDirection=asc&sortColumn=default&shape=RD&hasVisualization=true&isFiltersExpanded=false&astorFilterActive=false&country=USA&language=en-us&currency=USD&productSet=BN&skus='
r <-  jsonlite::fromJSON(url2)
df2 <- r$results

使用 css 选择器 .row 搜索页面会产生 1002 个结果,而不是指示的所有菱形总数;所以,我认为围绕过滤器需要进行一些探索。


推荐阅读