可以像这样保存和读取对象
# Save as file
saveRDS(iris, "mydata.RDS")
# Read back in
readRDS("mydata.RDS")
但这似乎不适用于使用xml2::read_html()
制造的对象
library(rvest)
someobject <- read_html("https://stackoverflow.com/")
saveRDS(someobject, "someobject.RDS")
哪个创建了文件,但没有达到预期 即
readRDS("someobject.RDS")
Error in doc_is_html(x$doc) : external pointer is not valid
这是怎么回事,最简单的保存html对象的方法是什么,以便可以用最少的代码/繁琐的操作将其重新加载?
答案 0 :(得分:4)
要回答“正在发生的事情”:saveRDS
试图序列化要保存的对象。在这里,对象someobject
是包含元素someobject$doc
和someobject$node
的列表。元素的类型为externalptr
(外部指针),这意味着它们引用了保存在内存中的C数据结构。当外部指针被序列化时,引用将丢失。因此,错误“外部指针无效”。
您可以使用someobject
序列化as.character()
并将其传递给saveRDS
:
saveRDS(as.character(someobject), "someobject.RDS")
然后使用readRDS
和read_html
重新创建对象:
someobject <- read_html(readRDS("someobject.RDS"))
但是像其他人建议的那样使用write_html()
更容易。
答案 1 :(得分:3)
据我所知,使用 XML
和 RDS
文件的方法似乎相差相同数量的字符。对比了一下,原版和加载版的区别就在body节点上。
url <- "https://stackoverflow.com/"
html <- read_match(url)
html_node(html, "body") %>% html_text() %>% unlist() -> OBT
nchar(OBT)
28879
xml2::write_xml(html, "someobject1.xml")
html_node(html, "body") %>% html_text() %>% unlist() -> BT1
nchar(BT1)
28893
html %>% toString %>% saveRDS(., "someobject.RDS")
after2 <- readRDS("someobject.RDS") %>% read_html
html_node(html, "body") %>% html_text() %>% unlist()-> BT2
nchar(BT2)
28893
这表明两个加载的对象具有相同的字符数。 如果我们从所有文本对象中删除一个“\n”字符,数字应该相同。
BT1 %>% str_remove_all(.,"\n") %>% nchar(.)
27733
BT2 %>% str_remove_all(.,"\n") %>% nchar(.)
27733
OBT %>% str_remove_all(.,"\n") %>% nchar(.)
27733
答案 2 :(得分:1)
我们可以使用write_xml
软件包中的read_html
和xml2
before <- read_html("https://stackoverflow.com/")
xml2::write_xml(before, "someobject1.xml")
after <- xml2::read_html("someobject1.xml")
但是,identical
返回FALSE
identical(before, after)
#[1] FALSE
但它们两个的查询似乎都返回相同的结果
library(rvest)
before %>% html_nodes("div")
after %>% html_nodes("div")
答案 3 :(得分:0)
在保存之前使用toString()
将xml_document
类转换为character
,就像这样
library(rvest)
someobject <- read_html("https://stackoverflow.com/")
someobject %>% toString %>% saveRDS(., "someobject.RDS")
newobject <- readRDS("someobject.RDS") %>% read_html
请注意,这些对象并不完全相同(我不确定为什么)。
identical(someobject, newobject)
# [1] FALSE