我已经为这个问题苦苦挣扎了两天,希望这里的人对如何避免这种麻烦有一些想法。我一直在学习rvest
软件包,我想刮擦当地餐馆的评论,以查看评论的评分和情绪随时间的变化。
为此,我使用rvest
和其他一些tidyverse
软件包构建了三个函数。该功能可刮擦每个评论的文本,等级和日期。我的目标是然后汇总到一个数据框,以便用于进一步分析。问题是yelp平台上的某些人要么更新先前的评论,要么提供餐厅的第二条评论。刮除评分时,我会从每个评论(包括这些更新/以前的评论)中获得评分。当我抓取日期和文本时,我没有得到更新/以前的评论。当我尝试将内容绑定在一起时,它会中断,因为每个函数都返回不同的长度向量。
如何识别这些更新的和以前的评论,然后在我的抓取功能的逻辑内跳过抓取它们?我创建了一个尽可能简单的示例,以演示该问题。
# create reprex for scraping issue
library(tidyverse)
library(lubridate)
library(rvest)
# example page with issue
url <- "https://www.yelp.com/biz/ottos-sausage-kitchen-and-meat-market-portland"
scrape_review_text <- function(link) {
# Scrape the text of the reviews
text <- link %>%
read_html() %>%
html_nodes(".review-content") %>% # content of reviews
html_text() %>%
str_remove("\\d{1,2}/\\d{1,2}/\\d{4}") %>% # clean strings
str_remove_all("\n") %>%
str_remove("\\d{1,2} check-in") %>%
str_trim()
return(text)
}
scrape_review_rating <- function(link) {
# Scrape the ratings of the reviews
rating <- link %>%
read_html() %>%
html_nodes(".rating-large") %>%
html_attr("title") %>%
str_extract("\\d.\\d") %>%
as.numeric()
return(rating)
}
scrape_review_date <- function(link) {
# Scrape the review date
review_dates <- link %>%
read_html() %>%
html_nodes(".review-content") %>%
html_text() %>%
str_extract("\\d{1,2}/\\d{1,2}/\\d{4}") %>%
mdy()
return(review_dates)
}
# apply functions
review_text <- scrape_review_text(url)
review_rating <- scrape_review_rating(url)
review_date <- scrape_review_date(url)
# notice the difference in the length of vectors returned
print(c(length(review_text), length(review_rating), length(review_date)))
#> [1] 20 23 20
# create a data frame to compare to sire
df <- tibble(date = review_date[1],
rating = review_rating[1],
text = review_text[1])
for (i in 2:length(review_text)) {
# iteratively add review content to compare with site
df[i, "date"] <- review_date[i]
df[i, "rating"] <- review_rating[i]
df[i, "text"] <- review_text[i]
}
如果打印df
,您会注意到当发生更新/以前的评论时,评论,评分和日期开始与网站上的有所不同。我希望能够以某种方式识别这些更新/以前的评论,并跳过它们的评分。我已经花了很多时间来处理div类,但是我看不到如何通过此标记来分离数据。