以下代码有效:
library(rvest)
library(plyr)
alaska <- c(1:49)
for (i in alaska) {
url <- "http://www.50states.com/facts/alaska.htm"
nodespath <- paste('//*[@id="content"]/div[1]/div[4]/ol/li[',i,']')
alaskafacts <- data.frame(facts = url %>% html() %>%
html_nodes(xpath =nodespath) %>% html_text())
alaskafacts$nm <- i
alaskafacts$facts <- alaskafacts$facts
result <- rbind.fill(result,alaskafacts)
}
我会得到这个结果:
我知道循环正在运行,因为如果我将代码更改为:
alaska <- c(1:48)
我会得到这个结果:
我遇到的问题是循环写入自身。我期待49行事实 - 我猜测循环擦除了先前的事实,然后写了一个新的 - 最后一个事实将永远是data.frame中的事实。
我在这里找到了一个示例:How can I use a loop to scrape website data for multiple webpages in R?,上面发布的代码遵循示例中的代码。然后我引用了这个例子:here。我认为上面的代码也遵循它。
我在底部的rbind调用遵循我在SO上找到的两个类似的例子,但没有按预期保存。
有什么建议吗?
答案 0 :(得分:2)
您需要在for循环之前预定义结果变量。目前每次循环结果都被覆盖。试试这个:
library(rvest)
library(plyr)
alaska <- c(1:49)
result<-data.frame()
for (i in alaska) {
url <- "http://www.50states.com/facts/alaska.htm"
....
有一种更快的方法可以在不使用for循环的情况下提取所请求的信息(并且事先了解所需的长度)。 rvest被矢量化以允许在一个语句中提取所有节点:
library(rvest)
url <- "http://www.50states.com/facts/alaska.htm"
page<-url %>% read_html()
resultsarray<-html_text(html_nodes(page, "ol.stripedList li"))
# "ol.stripedList li" is the html code for the list hierarchical
# li (list element underneath) an ol (ordered list) of class "stripedList"
resultsarray是一个包含49个事实的字符串数组,我将允许您将其转换为所需的数据帧。