如何将read_html的输出保存和读取为RDS文件?

时间:2019-09-03 03:08:38

标签: r rvest xml2

可以像这样保存和读取对象

# 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对象的方法是什么,以便可以用最少的代码/繁琐的操作将其重新加载?

4 个答案:

答案 0 :(得分:4)

要回答“正在发生的事情”:saveRDS试图序列化要保存的对象。在这里,对象someobject是包含元素someobject$docsomeobject$node的列表。元素的类型为externalptr(外部指针),这意味着它们引用了保存在内存中的C数据结构。当外部指针被序列化时,引用将丢失。因此,错误“外部指针无效”。

您可以使用someobject序列化as.character()并将其传递给saveRDS

saveRDS(as.character(someobject), "someobject.RDS")

然后使用readRDSread_html重新创建对象:

someobject <- read_html(readRDS("someobject.RDS"))

但是像其他人建议的那样使用write_html()更容易。

一些讨论in this Github issue thread

答案 1 :(得分:3)

据我所知,使用 XMLRDS 文件的方法似乎相差相同数量的字符。对比了一下,原版和加载版的区别就在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_htmlxml2

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