亚马逊评论 R 中的网络抓取:当其中一条评论来自另一个国家时,如何避免 运行 出错?
Amazon reviews web scraping in R: how to avoid running into an error, when one of the reviews is from another country?
为了获得一些有趣的 NLP 数据,我刚开始在 R 中做一些基本的网络抓取。我的目标是尽可能多地从亚马逊收集产品评论。我的第一次基本试验成功了,但现在我 运行 出错了。
您可以从我的代表中的 url 中查看,该产品有 3 页评论。如果我刮掉第一个和第二个,一切正常。第三页是国外客户的评价。
当我试图抓取第三页时,我收到一条错误消息,指出我的 tibble 列没有兼容的尺寸。我该如何解释以及如何避免错误?
如果我从抓取函数中删除 review_star 和 review_title,错误也会消失。
library(pacman)
pacman::p_load(RCurl, XML, dplyr, rvest)
#### SCRAPE
scrape_amazon <- function(page_num){
url_reviews <- paste0("https://www.amazon.de/Lavendel-%C3%96L-Fein-kbA-%C3%84therisch/product-reviews/B00EXBKQDS/ref=cm_cr_getr_d_paging_btm_next_3?ie=UTF8&reviewerType=all_reviews&pageNumber=",page_num)
doc <- read_html(url_reviews)
# Review Title
doc %>%
html_nodes("[class='a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold']") %>%
html_text() -> review_title
# Review Text
doc %>%
html_nodes("[class='a-size-base review-text review-text-content']") %>%
html_text() -> review_text
# Number of stars in review
doc %>%
html_nodes("[data-hook='review-star-rating']") %>%
html_text() -> review_star
# date
date <- doc %>%
html_nodes("#cm_cr-review_list .review-date") %>%
html_text() %>%
gsub(".*on ", "", .)
# author
author <- doc %>%
html_nodes("#cm_cr-review_list .a-profile-name") %>%
html_text()
# Return a tibble
tibble(review_title,
review_text,
review_star,
date,
author,
page = page_num) %>% return()
}
# extract testing
df <- scrape_amazon(page_num = 3)
因此,我通常使用的几种方法涉及某些列表可能在 html 中缺少 items/differences 的情况:
- 找到一个 css 选择器列表,其中 returns 列表作为可迭代的(列表列表)。在这种情况下,可以使用
[id^='customer_review']
。如果您在浏览器开发工具中对此进行测试,您可以检查匹配项的数量。这应该是一个 parent 节点列表,其中包含您想要的所有项目(每个列表)。
- 在嵌套的
map_dfr(), data.frame()
调用中循环列表并定位各种 child 节点,这样 a) 你得到一个数据框 b) 你得到一个很好的 NA 返回丢失的项目。
- 使用开发工具 F12 检查每个 css 选择器列表返回的节点列表的长度,以了解项目可能丢失的位置,例如
您对第 3 页的评分选择器:
对于基于 non-Germany 的列表
,它忽略了 HTML 中的差异
data-hook="cmps-review-star-rating"
将其与预先测试进行比较 re-writing 为:
N.B。 1) 图像中的列表中有一个领先的 id 选择器,用于限制我们将迭代的相同 nodeList,即排除 Top +ve 和 Top critical review 项目 2) rvest 返回的 html 内容将根据页面源而不是浏览器呈现的内容,因此值得根据该内容对选择器进行二次检查。我通常通过在线交互式演示工具在 jsoup 中使用 Fetch URL(尽管您可能更喜欢像 Postman 这样的东西,您可以在其中更轻松地测试其他请求方面,例如 headers.
jsoup is a Java library for working with real-world HTML. It provides
a very convenient API for fetching URLs and extracting and
manipulating data, using the best of HTML5 DOM methods and CSS
selectors.
使用 FF,您似乎还可以获得一个方便的花花公子下拉菜单来帮助选择 child DOM 个元素:
- 如下所示,更喜欢更短的 css 选择器列表,看起来更稳定 relationships/attributes,以减轻 html 随着时间的推移
的变化
TODO:您可能希望将一些类型转换作为直接项目实施
library(pacman)
pacman::p_load(RCurl, XML, dplyr, rvest, purrr)
#### SCRAPE
scrape_amazon <- function(page_num) {
url_reviews <- paste0("https://www.amazon.de/Lavendel-%C3%96L-Fein-kbA-%C3%84therisch/product-reviews/B00EXBKQDS/ref=cm_cr_getr_d_paging_btm_next_3?ie=UTF8&reviewerType=all_reviews&pageNumber=", page_num)
doc <- read_html(url_reviews)
map_dfr(doc %>% html_elements("[id^='customer_review']"), ~ data.frame(
review_title = .x %>% html_element(".review-title") %>% html_text2(),
review_text = .x %>% html_element(".review-text-content") %>% html_text2(),
review_star = .x %>% html_element(".review-rating") %>% html_text2(),
date = .x %>% html_element(".review-date") %>% html_text2() %>% gsub(".*vom ", "", .),
author = .x %>% html_element(".a-profile-name") %>% html_text2(),
page = page_num
)) %>%
as_tibble %>%
return()
}
# extract testing
df <- scrape_amazon(page_num = 3)
# df <- scrape_amazon(page_num = 2)
为了获得一些有趣的 NLP 数据,我刚开始在 R 中做一些基本的网络抓取。我的目标是尽可能多地从亚马逊收集产品评论。我的第一次基本试验成功了,但现在我 运行 出错了。
您可以从我的代表中的 url 中查看,该产品有 3 页评论。如果我刮掉第一个和第二个,一切正常。第三页是国外客户的评价。
当我试图抓取第三页时,我收到一条错误消息,指出我的 tibble 列没有兼容的尺寸。我该如何解释以及如何避免错误?
如果我从抓取函数中删除 review_star 和 review_title,错误也会消失。
library(pacman)
pacman::p_load(RCurl, XML, dplyr, rvest)
#### SCRAPE
scrape_amazon <- function(page_num){
url_reviews <- paste0("https://www.amazon.de/Lavendel-%C3%96L-Fein-kbA-%C3%84therisch/product-reviews/B00EXBKQDS/ref=cm_cr_getr_d_paging_btm_next_3?ie=UTF8&reviewerType=all_reviews&pageNumber=",page_num)
doc <- read_html(url_reviews)
# Review Title
doc %>%
html_nodes("[class='a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold']") %>%
html_text() -> review_title
# Review Text
doc %>%
html_nodes("[class='a-size-base review-text review-text-content']") %>%
html_text() -> review_text
# Number of stars in review
doc %>%
html_nodes("[data-hook='review-star-rating']") %>%
html_text() -> review_star
# date
date <- doc %>%
html_nodes("#cm_cr-review_list .review-date") %>%
html_text() %>%
gsub(".*on ", "", .)
# author
author <- doc %>%
html_nodes("#cm_cr-review_list .a-profile-name") %>%
html_text()
# Return a tibble
tibble(review_title,
review_text,
review_star,
date,
author,
page = page_num) %>% return()
}
# extract testing
df <- scrape_amazon(page_num = 3)
因此,我通常使用的几种方法涉及某些列表可能在 html 中缺少 items/differences 的情况:
- 找到一个 css 选择器列表,其中 returns 列表作为可迭代的(列表列表)。在这种情况下,可以使用
[id^='customer_review']
。如果您在浏览器开发工具中对此进行测试,您可以检查匹配项的数量。这应该是一个 parent 节点列表,其中包含您想要的所有项目(每个列表)。 - 在嵌套的
map_dfr(), data.frame()
调用中循环列表并定位各种 child 节点,这样 a) 你得到一个数据框 b) 你得到一个很好的 NA 返回丢失的项目。 - 使用开发工具 F12 检查每个 css 选择器列表返回的节点列表的长度,以了解项目可能丢失的位置,例如
您对第 3 页的评分选择器:
对于基于 non-Germany 的列表
,它忽略了 HTML 中的差异data-hook="cmps-review-star-rating"
将其与预先测试进行比较 re-writing 为:
N.B。 1) 图像中的列表中有一个领先的 id 选择器,用于限制我们将迭代的相同 nodeList,即排除 Top +ve 和 Top critical review 项目 2) rvest 返回的 html 内容将根据页面源而不是浏览器呈现的内容,因此值得根据该内容对选择器进行二次检查。我通常通过在线交互式演示工具在 jsoup 中使用 Fetch URL(尽管您可能更喜欢像 Postman 这样的东西,您可以在其中更轻松地测试其他请求方面,例如 headers.
jsoup is a Java library for working with real-world HTML. It provides a very convenient API for fetching URLs and extracting and manipulating data, using the best of HTML5 DOM methods and CSS selectors.
使用 FF,您似乎还可以获得一个方便的花花公子下拉菜单来帮助选择 child DOM 个元素:
- 如下所示,更喜欢更短的 css 选择器列表,看起来更稳定 relationships/attributes,以减轻 html 随着时间的推移 的变化
TODO:您可能希望将一些类型转换作为直接项目实施
library(pacman)
pacman::p_load(RCurl, XML, dplyr, rvest, purrr)
#### SCRAPE
scrape_amazon <- function(page_num) {
url_reviews <- paste0("https://www.amazon.de/Lavendel-%C3%96L-Fein-kbA-%C3%84therisch/product-reviews/B00EXBKQDS/ref=cm_cr_getr_d_paging_btm_next_3?ie=UTF8&reviewerType=all_reviews&pageNumber=", page_num)
doc <- read_html(url_reviews)
map_dfr(doc %>% html_elements("[id^='customer_review']"), ~ data.frame(
review_title = .x %>% html_element(".review-title") %>% html_text2(),
review_text = .x %>% html_element(".review-text-content") %>% html_text2(),
review_star = .x %>% html_element(".review-rating") %>% html_text2(),
date = .x %>% html_element(".review-date") %>% html_text2() %>% gsub(".*vom ", "", .),
author = .x %>% html_element(".a-profile-name") %>% html_text2(),
page = page_num
)) %>%
as_tibble %>%
return()
}
# extract testing
df <- scrape_amazon(page_num = 3)
# df <- scrape_amazon(page_num = 2)