R语言网页爬取循环返回索引而非结果,如何修正?
问题分析与修正方案
错误原因
你的循环写法确实存在问题,导致res存储的是索引而非爬取结果,核心原因有两点:
withTimeout返回值覆盖结果:withTimeout代码块会返回块内最后一行代码的执行结果,你在块内最后一行写了print(i),而print(i)的返回值就是i本身,因此res[[i]] <- withTimeout(...)实际上把索引i赋值给了res[[i]],覆盖了之前在块内赋值的res[[i]] <- r_i。- URL取值方式有误:如果
url是列表对象,url[i]返回的是长度为1的子列表,而fromJSON需要的是字符型URL字符串,应该用url[[i]]提取列表中的单个元素。
修正后的代码
以下是两种可行的修正方式:
方式一:让withTimeout直接返回爬取结果
library(R.utils) library(jsonlite) # 显式加载fromJSON所在的包 res <- vector("list", length = length(url)) # 适配url列表的实际长度 for (i in seq_along(url)) { print(i) tryCatch({ # withTimeout返回代码块最后一行的结果,直接赋值给res[[i]] res[[i]] <- withTimeout({ url_i <- url[[i]] # 提取列表中的URL字符串 r_i <- data.frame(fromJSON(url_i)) r_i # 将爬取结果设为代码块的返回值 }, timeout = 1) print(paste("成功爬取第", i, "个URL")) }, TimeoutException = function(ex) { message(paste("第", i, "个URL超时,跳过")) res[[i]] <- NULL }) }
方式二:保留块内赋值,调整代码顺序
library(R.utils) library(jsonlite) res <- vector("list", length = length(url)) for (i in seq_along(url)) { print(i) tryCatch({ withTimeout({ url_i <- url[[i]] r_i <- data.frame(fromJSON(url_i)) res[[i]] <- r_i # 直接给res赋值 print(paste("成功爬取第", i, "个URL")) }, timeout = 1) }, TimeoutException = function(ex) { message(paste("第", i, "个URL超时,跳过")) res[[i]] <- NULL }) }
额外说明
- 必须提前加载
jsonlite包,fromJSON是该包的函数,原代码未显式加载可能引发报错。 - 用
seq_along(url)代替1:10,可让循环自动适配url列表的实际长度,提升代码灵活性。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

