Rvest循环抓取TripAdvisor酒店评论时返回空值的解决方法求助
我明白你遇到的问题了——用rvest循环爬取TripAdvisor评论时,随机出现的空值确实很头疼,明明分步跑大多没问题,批量循环就时不时掉链子。咱们来一步步解决这个问题:
问题根源分析
这种随机空值大概率是这几个原因导致的:
- 反爬机制拦截:短时间内频繁请求,网站会临时限制你的访问,返回空页面或者部分内容
- 重复请求浪费资源:你原来的代码里每次循环两次调用
read_html(url),既拖慢速度又增加被拦截的概率 - 节点选择器不够稳健:嵌套过深的选择器容易因为页面微小变化失效
- 页面加载不完全:偶尔网络波动会导致页面没完全加载就被解析
优化后的解决方案代码
下面是修改后的脚本,针对上述问题做了全方位优化:
library(rvest) library(dplyr) # 初始化空数据框 df <- data.frame(review_text = character(), rating = numeric(), stringsAsFactors = FALSE) x <- 0 max_retries <- 3 # 失败后最多重试3次 # 先爬50页(对应250条评论,足够满足你至少100条的需求) for(i in 1:50){ url <- paste0("https://www.tripadvisor.com/Hotel_Review-g295424-d7760386-Reviews-or", x, "-Hyatt_Regency_Dubai_Creek_Heights-Dubai_Emirate_of_Dubai.html") x <- x + 5 success <- FALSE retry_count <- 0 # 失败重试机制 while(!success && retry_count < max_retries){ tryCatch({ # 只读取一次页面,避免重复请求 page <- read_html(url) # 优化评论文本选择器,更直接定位核心内容 reviews <- page %>% html_nodes(".hotels-hotel-review-community-content-review-list-parts-ExpandableReview__reviewText--2OVqJ") %>% html_text(trim = TRUE) # 优化评分提取逻辑,避免空值报错 rating <- page %>% html_nodes(".hotels-hotel-review-community-content-review-list-parts-RatingLine__bubbles--3d2Be span") %>% html_attr("class") %>% # 用匿名函数处理拆分,避免sapply的潜在问题 lapply(function(class_str) strsplit(class_str, "_")[[1]][4]) %>% unlist() %>% as.numeric() # 确保抓取到有效数据再合并 if(length(reviews) > 0 && length(rating) > 0){ # 对齐评论和评分的长度,防止偶尔出现数量不一致的情况 min_len <- min(length(reviews), length(rating)) temp_df <- data.frame( review_text = reviews[1:min_len], rating = rating[1:min_len], stringsAsFactors = FALSE ) df <- bind_rows(df, temp_df) success <- TRUE cat("成功抓取第", i, "页,当前总评论数:", nrow(df), "\n") } else { warning("第", i, "页未抓取到有效数据,重试中...") retry_count <- retry_count + 1 Sys.sleep(runif(1, 2, 4)) # 重试前等待更久,降低被拦截概率 } }, error = function(e){ warning("第", i, "页请求失败:", e$message, ",重试中...") retry_count <- retry_count + 1 Sys.sleep(runif(1, 2, 4)) }) } # 每次循环后随机等待1-3秒,模拟人类浏览节奏 Sys.sleep(runif(1, 1, 3)) } # 输出最终结果统计 cat("抓取完成,总评论数:", nrow(df), "\n") head(df)
关键优化点说明
- 单次页面读取:把
read_html(url)移到循环内部的最前面,只请求一次页面就完成评论和评分的提取,减少请求次数 - 失败重试机制:用
tryCatch包裹请求逻辑,遇到错误或者空数据时自动重试,避免单次失败就丢失整页数据 - 随机延迟:每次循环后加入1-3秒的随机等待,重试时等待更久,有效规避反爬拦截
- 稳健的选择器:简化了评论和评分的选择器路径,降低因为页面微小变化导致的失效概率
- 数据对齐处理:确保评论和评分的长度一致,避免合并数据框时出现错位问题
额外注意事项
- 如果还是偶尔出现空值,建议用
SelectorGadget工具重新确认页面的CSS选择器——TripAdvisor的class名偶尔会更新 - 不要盲目扩大循环次数,避免被网站封禁IP;如果需要爬大量数据,可以考虑使用代理IP(新手先从延迟和重试机制开始)
- 可以先测试小范围循环(比如10页),确认稳定后再扩大到250页
内容的提问来源于stack exchange,提问作者IliasWhoElse
相关产品推荐
相关产品推荐

