使用R的rvest、polite包爬取小说章节时遇xml_find_all报错
批量爬取WordPress章节时
xml_find_all报错的解决方案 问题背景
使用tidyverse、polite、xml2爬取站点的章节内容:
- 通过右侧栏获取章节链接后,筛选出895个有效链接
- 单章节爬取代码可正常返回内容
- 编写批量爬取函数并通过
sapply执行时,触发错误:Error in UseMethod("xml_find_all") : no applicable method for 'xml_find_all' applied to an object of class "NULL"
错误原因
该报错核心是:批量爬取中存在无效/无法访问的链接,导致scrape()返回NULL。后续html_nodes()依赖XML/HTML对象执行,对NULL调用底层的xml_find_all函数就会触发该错误。常见诱因包括:
- 筛选后的部分链接本身无效(如已删除的章节)
- 批量请求频率过高,被网站反爬机制拦截
- 网络波动导致部分请求失败
修复方案
在函数中加入错误处理、复用会话、添加请求延迟,确保批量爬取不会因单个链接失败而中断:
修改后的完整代码
library(tidyverse) library(polite) library(xml2) # 初始化礼貌会话(仅需执行一次) link <- "https://serialshmintardja.wordpress.com/" session <- bow(link, user_agent = "Hi, I'm webscraping for research") # 获取并筛选章节链接 chapter_links <- scrape(session) %>% html_nodes(".textwidget a") %>% html_attr("href") chapter_links <- chapter_links[4:898] # 带错误处理的章节爬取函数 get_chapter <- function(chapter_link, session) { # 添加1秒延迟,避免请求过于频繁 Sys.sleep(1) tryCatch({ # 复用初始会话,维持礼貌请求上下文 chapter_page <- nod(session, chapter_link) %>% scrape(verbose = TRUE) # 提取段落内容并拼接 chapter_content <- chapter_page %>% html_nodes("p") %>% html_text() %>% paste(collapse = ",") return(chapter_content) }, error = function(e) { # 捕获错误,返回NA并打印错误信息 message(paste("Failed to scrape:", chapter_link, "\nError:", e$message)) return(NA_character_) }) } # 执行批量爬取(lapply比sapply更易处理结果) chapter_contents <- lapply(chapter_links, get_chapter, session = session) # 转换为数据框方便后续处理 chapter_df <- tibble( link = chapter_links, content = unlist(chapter_contents) ) # 过滤掉爬取失败的条目 chapter_df <- chapter_df %>% filter(!is.na(content))
关键优化点
- 会话复用:用
nod(session, chapter_link)替代每次新建bow,保持同一会话的请求标识,符合礼貌爬取原则 - 错误捕获:
tryCatch包裹请求逻辑,单个链接失败时返回NA并打印错误,不会中断整个批量任务 - 请求延迟:
Sys.sleep(1)降低请求频率,减少被网站反爬拦截的概率 - 结果整理:用
tibble存储链接和内容,方便后续清洗和分析
内容的提问来源于stack exchange,提问作者Helmasan
相关产品推荐
相关产品推荐

