在R中保存xml节点
我对使用R和xml进行抓取非常陌生,我对保存和加载数据集有一个问题 我使用如下代码获取了一个相当大的数据集在R中保存xml节点,r,xml,rvest,R,Xml,Rvest,我对使用R和xml进行抓取非常陌生,我对保存和加载数据集有一个问题 我使用如下代码获取了一个相当大的数据集 data<-list() for(i in page[1:10]){ pages<-read_html(paste0("http://www.gbig.org/buildings/", i)) nodes<-html_nodes(pages, '.badge-info .cert-badge , .event , .date , .media-heading a
data<-list()
for(i in page[1:10]){
pages<-read_html(paste0("http://www.gbig.org/buildings/", i))
nodes<-html_nodes(pages, '.badge-info .cert-badge , .event ,
.date , .media-heading a , .truncated , .location , .buildings-type')
data[[i]] <-nodes
}
当我加载它并再次尝试使用它时,会收到一条特定的错误消息。我做错了什么?保存和加载xml节点的最佳方法是什么
{xml_nodeset (10)}
Error in node_write_character(x$node, options = options, encoding = encoding) :
external pointer is not valid
编辑
我尝试的加载命令是:
load("trials.RData")
谢谢它不起作用的原因是节点是一个“xptr”或“外部指针”,并且在保存到R数据文件时没有序列化。
xml2
包存储库和R文档中的各种其他地方确实对此有警告性的指导,但没有人再使用RTFM了#叹息
解决您的问题并阻止您自己在将来再次添加站点的一种方法是从节点提取数据,而不是尝试保存原始节点并保留源页面的副本,这样您就可以刮取这些数据,而不是返回站点并浪费它们的带宽(再次)
我们需要一些软件包:
library(rvest)
library(httr)
library(tidyverse)
您应该始终从查看网站robots.txt
和服务条款/条款和条件开始。该站点有一个robots.txt
,但没有ToS/T&C,因此我们将查看它们是否允许您尝试执行以下操作:
robotstxt::get_robotstxt(urltools::domain("http://www.gbig.org/buildings/")) %>%
cat()
## # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
## #
## # To ban all spiders from the entire site uncomment the next two lines:
## # User-Agent: *
## # Disallow: /
## User-Agent: *
## Crawl-delay: 10
## Disallow: /beta_invites
## Disallow: /admin
## Disallow: /search
## Disallow: /green_schools
## Disallow: /api
## Disallow: /places/8194/activities
## Disallow: /places/935/activities
因此,我们需要在页面请求之间使用10秒的爬网延迟,您最好希望您使用/search
或/api
路径来获取页面列表时没有违反技术控制
此外,由于我们将采用另一种方法来获取所需的节点,因此我们稍后将需要此功能:
c(
".badge-info .cert-badge", ".event", ".date" , ".media-heading a",
".truncated", ".location" , ".buildings-type"
) -> target_nodes
而且,我们以后也需要清理
clean_node_names <- function(x) {
x <- tolower(x)
x <- gsub("[[:punct:][:space:]]+", "_", x)
x <- gsub("_+", "_", x)
x <- gsub("(^_|_$)", "", x)
x <- make.unique(x, sep = "_")
x
}
最后,迭代这些URL并:
- 停顿
- 读这一页
- 通过从每个CSS选择器路径提取节点文本来构建数据帧;它们的长度参差不齐,所以我们将它们全部列为
list()
- 保存HTML页面的字符源
map_df(building_urls, ~{
pb$tick()$print()
Sys.sleep(10)
x <- read_html(.x)
map(target_nodes, html_nodes, x=x) %>%
map(html_text) %>%
set_names(clean_node_names(target_nodes)) %>%
map(~list(.x)) %>%
as_data_frame() -> tmpdf
tmpdf$src_html <- as.character(pg)
tmpdf
}) -> xdf
现在,这是一个原始向量列表:
str(bldg_lst)
## List of 12
## $ : raw [1:4273] 58 0a 00 00 ...
## $ : raw [1:4027] 58 0a 00 00 ...
## $ : raw [1:3164] 58 0a 00 00 ...
## $ : raw [1:7718] 58 0a 00 00 ...
## $ : raw [1:2996] 58 0a 00 00 ...
## $ : raw [1:2908] 58 0a 00 00 ...
## $ : raw [1:4506] 58 0a 00 00 ...
## $ : raw [1:4127] 58 0a 00 00 ...
## $ : raw [1:2982] 58 0a 00 00 ...
## $ : raw [1:3034] 58 0a 00 00 ...
## $ : raw [1:1800] 58 0a 00 00 ...
## $ : raw [1:1877] 58 0a 00 00 ...
你可以省下来
当读回时,您将执行以下操作:
map(bldg_lst, xml_unserialize)
## [[1]]
## {xml_nodeset (65)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">208 N Capitol Ave, Lansing, MI, USA</p>
## ...
##
## [[2]]
## {xml_nodeset (62)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">3825 Wisconsin Ave NW, Washington, DC, USA</p>
## ...
##
## [[3]]
## {xml_nodeset (54)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> San Francisco, CA, USA</p>
## ...
##
## [[4]]
## {xml_nodeset (127)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> Washington, DC, USA</p>
## ...
##
## [[5]]
## {xml_nodeset (50)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">4940 N 118th St, Omaha, NE, USA</p>
## ...
##
## [[6]]
## {xml_nodeset (47)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> Dallas, TX, USA</p>
## ...
##
### (etc)
地图(建筑lst、xml非序列化)
## [[1]]
##{xml_nodeset(65)}
##[1]是的。从技术上讲,这是重复的,但请参见针对替代方法和使用dup答案中提及的序列化的附加方法提供的答案。
map_df(building_urls, ~{
pb$tick()$print()
Sys.sleep(10)
x <- read_html(.x)
map(target_nodes, html_nodes, x=x) %>%
map(html_text) %>%
set_names(clean_node_names(target_nodes)) %>%
map(~list(.x)) %>%
as_data_frame() -> tmpdf
tmpdf$src_html <- as.character(pg)
tmpdf
}) -> xdf
glimpse(xdf)
## Observations: 12
## Variables: 8
## $ badge_info_cert_badge <list> [<"Case Study", "Case Study", "Case Stu...
## $ event <list> [<"Whole Building Design Guide Case Stu...
## $ date <list> [<"06/20/2014", "08/13/2013", "08/13/20...
## $ media_heading_a <list> [<"The Mutual Building Christman Compa...
## $ truncated <list> ["\nThe Christman Building LEED-EB, The...
## $ location <list> ["208 N Capitol Ave, Lansing, MI, USA",...
## $ buildings_type <list> ["\n\nThe Christman Building\n", "\n\nS...
## $ src_html <chr> "<!DOCTYPE html>\n<html lang=\"en\">\n<h...
pb <- progress_estimated(length(building_urls))
map(building_urls, ~{
pb$tick()$print()
Sys.sleep(10)
read_html(.x) %>%
html_nodes(
'.badge-info .cert-badge , .event , .date , .media-heading a , .truncated , .location , .buildings-type'
) %>%
xml_serialize(NULL) -> nodes
nodes
}) -> bldg_lst
str(bldg_lst)
## List of 12
## $ : raw [1:4273] 58 0a 00 00 ...
## $ : raw [1:4027] 58 0a 00 00 ...
## $ : raw [1:3164] 58 0a 00 00 ...
## $ : raw [1:7718] 58 0a 00 00 ...
## $ : raw [1:2996] 58 0a 00 00 ...
## $ : raw [1:2908] 58 0a 00 00 ...
## $ : raw [1:4506] 58 0a 00 00 ...
## $ : raw [1:4127] 58 0a 00 00 ...
## $ : raw [1:2982] 58 0a 00 00 ...
## $ : raw [1:3034] 58 0a 00 00 ...
## $ : raw [1:1800] 58 0a 00 00 ...
## $ : raw [1:1877] 58 0a 00 00 ...
map(bldg_lst, xml_unserialize)
## [[1]]
## {xml_nodeset (65)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">208 N Capitol Ave, Lansing, MI, USA</p>
## ...
##
## [[2]]
## {xml_nodeset (62)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">3825 Wisconsin Ave NW, Washington, DC, USA</p>
## ...
##
## [[3]]
## {xml_nodeset (54)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> San Francisco, CA, USA</p>
## ...
##
## [[4]]
## {xml_nodeset (127)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> Washington, DC, USA</p>
## ...
##
## [[5]]
## {xml_nodeset (50)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location">4940 N 118th St, Omaha, NE, USA</p>
## ...
##
## [[6]]
## {xml_nodeset (47)}
## [1] <h2 class="buildings-page-title buildings-type"><img alt="Building" ...
## [2] <p class="location"> Dallas, TX, USA</p>
## ...
##
### (etc)