在嵌套For循环中嵌入if语句的论坛爬虫问题排查
问题分析与修正方案
核心错误点
- URL读取错误:
page = read_html(page)变量名重复,需用拼接好的link作为参数,否则第一次循环时page未定义会直接报错。 - 下一页判断逻辑缺陷:未找到下一页按钮时,
html_attr('rel')返回空向量,直接用== "next"做条件会触发错误(if要求逻辑值长度为1),需先判断节点是否存在。 - 正则表达式无效:
str_remove('p*')中的p*是正则语法,仅匹配0个或多个字母p,无法正确处理分页路径,若原URL不含分页,这一步完全多余。 - 数据拼接效率低下:循环中用
rbind反复拼接数据框会大幅拖慢性能,改用列表收集数据后一次性绑定更高效。
修正后的代码
library(tidyverse) library(rvest) library(lubridate) df_comments_list <- list() # 用列表存储每页数据,提升性能 for (j in df_iva$url) { for (i in seq(from = 1, to = 100000, by = 1)){ link <- paste0(j, "/p", i) page <- read_html(link) # 修正:使用拼接好的分页URL Sys.sleep(runif(1, min=1.29, max=4.89)) # 修正标题提取:仅去除固定前缀即可 post_title <- str_remove(j, 'https://forums.moneysavingexpert.com/discussion/') user <- page %>% html_nodes(xpath = '//a[@class="Username js-userCard"]') %>% html_attr('data-userid') date_time <- page %>% html_nodes(xpath = '//div[@class="DataBox DataBox-Comments"]//div[@class="Meta RecordMeta"]//span[@class="MItem DateCreated"]//a//time') %>% html_attr('datetime') %>% ymd_hms() # 将当前页数据存入列表 df_comments_list[[length(df_comments_list) + 1]] <- tibble(post_title, user, date_time) # 修正下一页判断:先检查节点存在性,再验证rel属性 next_btn <- page %>% html_nodes(xpath = '//div[@class="P PagerWrap"]//a[@class="Next"]') if (length(next_btn) > 0 && html_attr(next_btn, 'rel') == "next") { print(link) } else { print("finished") break } } print(paste0("##### ", j, " ####")) Sys.sleep(runif(1, min=3.29, max=12.89)) } # 一次性绑定所有页面的数据 df_comments <- bind_rows(df_comments_list)
额外优化建议
- 增加错误捕获:用
tryCatch包裹read_html,避免单个页面请求失败导致整个爬虫中断。 - 日志记录:除打印链接外,可将爬取状态写入本地日志文件,方便后续排查问题。
- 分页适配:若论坛主URL本身就是第一页(无需
/p1),可调整循环起始为2,先单独爬取j作为第一页数据。
内容的提问来源于stack exchange,提问作者Robert Chestnutt
相关产品推荐
相关产品推荐

