#html #r #web-scraping #rvest
#HTML #r #очистка веб-страниц #rvest
Вопрос:
Я пытаюсь очистить средние оценки пользователей (из 5 звезд) и количество оценок со страницы продавца вина. Похоже, что среднее количество звезд, равное 5, находится в button
теге, в то время как количество оценок находится в meta
теге.
Вот HTML:
<div class="bv_avgRating_component_container notranslate">
<button
type="button"
class="bv_avgRating"
aria-expanded="false"
aria-label="average rating value is 4.5 of 5."
id="avg-rating-button"
role="link"
itemprop="ratingValue"
>
4.5
</button>
</div>
<div class="bv_numReviews_component_container">
<meta itemprop="reviewCount" content="95" />
amp;nbsp;
<button
type="button"
class="bv_numReviews_text"
aria-label="Read 95 Reviews"
aria-expanded="false"
id="num-reviews-button"
role="link"
>
(95)
</button>
</div>
Что я пробовал:
library(tidyverse)
library(rvest)
x <- "/wine/red-wine/cabernet-sauvignon/amici-cabernet-sauvignon-napa/p/20095750?s=918amp;igrules=true"
ratings <- read_html(paste0("https://www.totalwine.com", x)) %>%
html_nodes(xpath = '//meta[@itemprop="reviewCount"]') %>%
html_attr('content') #returns character(empty)
ratings <- read_html(paste0("https://www.totalwine.com", x)) %>%
html_nodes("meta") %>%
html_attr("content") #returns chr [1:33]
ratings <- read_html(paste0("https://www.totalwine.com", x)) %>%
html_nodes("div meta") %>%
html_attr("content") #returns chr [1:21]
ratings <- read_html(paste0("https://www.totalwine.com", x)) %>%
html_nodes("meta[itemprop=reviewCount]") %>%
html_attr("content") #returns character(empty)
В конце концов, два момента, которые я пытаюсь извлечь, — это 4.5
и content="95"
.
Ответ №1:
Откройте вкладку Network инструмента разработки и перезагрузите страницу, вы увидите, что на этой странице загружаются данные из https://www.totalwine.com/product/api/product/product-detail/v1/getProduct/20095750-1?shoppingMethod=INSTORE_PICKUPamp;state=US-CAamp;storeId=918
(которые являются файлом JSON): Получите желаемый рейтинг и количество просмотров с помощью этого:
data <- jsonlite::fromJSON("https://www.totalwine.com/product/api/product/product-detail/v1/getProduct/20095750-1?shoppingMethod=INSTORE_PICKUPamp;state=US-CAamp;storeId=918")
rating <- data$customerAverageRating
reviews_count <- data$customerReviewsCount
Обновление: Если вы новичок в области веб-очистки, вам, вероятно, интересно, почему я вообще не использовал rvest
. Дело в том, что эта страница использует JS для генерации содержимого и rvest
не может обрабатывать JS, она только считывает HTML перед загрузкой JS.
Комментарии:
1. спасибо @xwhitelight! Я ничего не знал о JS. Этот фрагмент является частью функции, в которой я намерен получить 20 различных переменных для ~ 5 тыс. вин. Похоже, что в JSON есть вся необходимая мне информация, так что это очень полезно! Все, что мне нужно сделать, это установить идентификатор продукта (20095750) в path в качестве моего аргумента. Могу ли я спросить, как вы узнали, что именно этот конкретный URL содержит информацию?
2. @laBouz После открытия вкладки Network и перезагрузки страницы появляется довольно много запросов. Вот где возникает «опыт», я вроде как догадываюсь, какой запрос содержит информацию. Обратите внимание, что не обязательно, чтобы запрос всегда содержал необходимую вам информацию.