在R语言中如何将html_node转换为可操作的列表格式?
首先咱们先理清几个核心问题:你用html_node(".project-row")拿到的是单个父节点(即class为project-row的div),而非里面的10个子元素,这就是为什么length(temp_list)返回的不是10;而且直接对html_node对象用gsub或lapply会报错,因为它是外部指针类型,不是可直接操作的字符向量。
下面是一步步的解决方案:
1. 正确提取所有需要的子节点
先获取.project-row父节点,再提取里面所有的dt和dd元素(也就是你输出里的10个条目):
library(rvest) library(dplyr) source <- "https://www.ifad.org/en/web/operations/-/project/1100000001" html_out <- read_html(source) # 先拿到父节点,再提取所有子节点(dt和dd) parent_node <- html_out %>% html_node(".project-row") child_nodes <- parent_node %>% html_nodes("dt, dd")
现在child_nodes是包含所有10个元素的xml_nodeset对象,length(child_nodes)会返回10,这才是你需要的目标集合。
2. 转换为可处理的文本向量
用html_text()函数把节点转换成纯文本内容,这一步会自动提取每个节点的文本:
raw_text <- child_nodes %>% html_text()
此时raw_text是一个字符向量,每个元素对应一个节点的文本,示例输出如下:
[1] "Status: Closed" "Country" "Dominican Republic" [4] "Approval Date" "19 December 1979" "Duration" [7] "1979 - 1988" "Sector" "Settlement" [10]"Total Project Cost "
3. 清洗文本(去除空格和换行)
直接对字符向量批量处理,不用循环:
clean_text <- raw_text %>% gsub("\r\n", "", .) %>% gsub("^ *|(?<= ) | *$", "", ., perl = TRUE)
注意先移除换行再处理多余空格,避免残留换行后的无效空格。
4. 整理成键值对列表(可选)
因为内容是dt(键)和dd(值)成对出现的,你可以把它们整理成命名列表,方便后续使用:
# 提取所有键(dt对应的文本,位置1,3,5...) keys <- clean_text[seq(1, length(clean_text), 2)] # 提取所有值(dd对应的文本,位置2,4,6...) values <- clean_text[seq(2, length(clean_text), 2)] # 组合成命名列表 project_info <- setNames(as.list(values), keys)
最终的project_info是一个清晰的命名列表,示例如下:
$`Status: Closed` NULL $Country [1] "Dominican Republic" $`Approval Date` [1] "19 December 1979" $Duration [1] "1979 - 1988" $Sector [1] "Settlement" $`Total Project Cost` NULL
(注:第一个和最后一个条目因为没有对应的值,所以显示为NULL,你可以根据实际需求调整处理逻辑)
为什么之前的脚本失效了?
你之前用as.list(.) %>% unlist()的方法,大概率是因为rvest版本更新后,as.list()对xml_nodeset的处理逻辑发生了变化。现在更推荐先通过html_text()把节点转成文本向量再操作,这种方式更稳定且可读性更强。
内容的提问来源于stack exchange,提问作者LololoTheGreat

