如何使用rvest选择性地抓取内容?

时间:2018-07-12 03:24:10

标签: r screen-scraping rvest

我已经为这个问题苦苦挣扎了两天,希望这里的人对如何避免这种麻烦有一些想法。我一直在学习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类,但是我看不到如何通过此标记来分离数据。

0 个答案:

没有答案