从数据库传URL到R中爬取数据报错,求代码修正
修正R语言网页爬取代码的错误
首先,咱们先拆解一下你遇到的错误原因:Error in doc_parse_file(...) : Expecting a single string value: [type=character; extent=455],这是因为base_url_2是一个data.frame对象,而非单个字符向量。当你把它传给lapply时,函数遍历的是data.frame的列(而非每个独立的URL字符串),导致read_html收到的是一整列URL,而不是它需要的单个URL,所以直接触发了报错。
下面是修正后的代码,我会把关键修改点一一说明:
原始问题代码
base_url_2 <- sqldf('select ORG_IMMEDIATE_PARENT_SRC from OA_output where row_id=1 ') df <- lapply(base_url_2,function(u) { try({ html_obj <- read_html(u) draft_table <- html_nodes(html_obj,'table') cik <- substr(u,start = 41,stop = 47) draft1 <- html_table(draft_table,fill = TRUE) final <- c(cik,draft1) }) }) check <- sapply(df, class) != "try-error" df <- df[check] data <- melt(df) data <- as.data.frame(data,row.names = NULL) data <- data[,1:2] names(data) <- c("CIK","Company") data2 <- transform(data, CIK = na.locf(CIK )) options(max.print = 5.5e5)
修正后的代码
# 关键修改1:提取URL为字符向量,而非保留data.frame结构 base_url_2 <- sqldf('select ORG_IMMEDIATE_PARENT_SRC from OA_output where row_id=1 ')$ORG_IMMEDIATE_PARENT_SRC df <- lapply(base_url_2, function(u) { tryCatch({ # 先过滤空值或无效URL if (is.na(u) || nchar(u) == 0) return(NULL) html_obj <- read_html(u) draft_table <- html_nodes(html_obj, 'table') cik <- substr(u, start = 41, stop = 47) # 关键修改2:处理html_table返回的列表,这里默认取第一个非空表格(可根据需求调整) draft1 <- html_table(draft_table, fill = TRUE)[[1]] # 关键修改3:结构化拼接数据,避免混乱的列表结构 if (!is.null(draft1) && nrow(draft1) > 0) { # 假设表格第一列是公司名称,可根据实际网页结构修改列索引 final <- data.frame(CIK = cik, Company = draft1[,1], stringsAsFactors = FALSE) return(final) } else { return(NULL) } }, error = function(e) { # 错误时输出提示并返回NULL,方便后续过滤 message(paste("处理URL失败", u, ":", e$message)) return(NULL) }) }) # 关键修改4:过滤掉无效的NULL结果(替代原有的try-error检查) df <- Filter(Negate(is.null), df) # 关键修改5:直接合并所有有效数据框,替代melt的复杂逻辑 data <- do.call(rbind, df) # 处理缺失的CIK(如果存在) data2 <- transform(data, CIK = na.locf(CIK)) options(max.print = 5.5e5)
关键修改说明
- 提取字符向量:通过
$ORG_IMMEDIATE_PARENT_SRC把data.frame中的URL列转换成字符向量,确保lapply遍历的是每个独立的URL。 - 优化错误处理:用
tryCatch替代try,既能捕获错误并输出提示,又能在出错时返回NULL,后续用Filter过滤更直观。 - 结构化数据拼接:不再用
c(cik, draft1)这种破坏结构的方式,直接构建包含CIK和公司信息的data.frame,后续合并更简单。 - 简化数据合并:用
do.call(rbind, df)替代melt,直接把所有有效数据框合并成一个大的data.frame,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Gautam Biswas
相关产品推荐
相关产品推荐

