从xml刮表

时间:2018-01-18 14:56:35

标签: r xml rvest rselenium

http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly.xml

我用rvest尝试了这个 -

 url <-"http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly.xml"



url %>%
read_html() %>%
 html_nodes("table") %>% html_table()

那没有用,所以接下来我尝试与selectorgadget一起使用 -

url %>%
read_html() %>%
 html_nodes(".report td") %>% html_table()

也没有骰子。我对Rselenium有一些经验,并且能够破解以下解决方案:

library(RSelenium)

remDr <- remoteDriver(port = 4567L, browserName = "phantomjs")
remDr$open()

remDr$navigate(url)
css <- paste0(".report td")
webElems <- remDr$findElements("css", css)
values <- unlist(sapply(webElems, function(x){x$getElementText()}))

其中&#34;值&#34;现在是一个向量,表中的每个条目,从左到右,从上到下。然后我可以将它基本解析成一个表 - 即每9个条目形成一行。

然而,这只是一个混乱,我希望能够尽可能地将其作为数据帧。任何建议表示赞赏,并提前感谢。

最后,我知道我使用了html_函数而不是rvest中的xml_函数 - 我之所以这么做是因为没有xml_table函数。我对HTML一般不太敏锐,所以如果有人能够对这些差异有所了解,我也会对此表示赞赏。

1 个答案:

答案 0 :(得分:1)

如果在未标识您的情况下调用浏览器,则只返回原始XML文件。它是一个格式良好的XML文件,因此处理起来非常简单(尽管获取嵌套记录有点费劲)。

以下内容会生成&#34; long&#34;来自XML的数据框:

library(xml2)
library(tidyverse)

doc <- read_xml("http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly.xml")

doc <- xml_ns_strip(doc) # this just reduces XPath query string complexities

数据是&#34;嵌套&#34;所以我们只需要&#34;不要&#34;它:

xml_find_all(doc, ".//DailyData") %>%
  map_df(~{
    xml_find_all(.x, ".//HourlyData") %>% 
      map_df(~{
        xml_find_all(.x, ".//FuelTotal") %>% 
          map_df(~{
            data_frame(
              fuel = xml_text(xml_find_first(.x, ".//Fuel"), trim=TRUE),
              output = xml_double(xml_find_first(.x, ".//Output"))
            )
          }) %>% 
          mutate(hour = xml_double(xml_find_first(.x, ".//Hour")))
      }) %>% 
      mutate(day = as.Date(xml_text(xml_find_first(.x, ".//Day"), trim=TRUE)))
  })
## # A tibble: 2,448 x 4
##       fuel output  hour        day
##      <chr>  <dbl> <dbl>     <date>
##  1 NUCLEAR  11671     1 2018-01-01
##  2     GAS   1583     1 2018-01-01
##  3   HYDRO   4152     1 2018-01-01
##  4    WIND    992     1 2018-01-01
##  5   SOLAR      0     1 2018-01-01
##  6 BIOFUEL      3     1 2018-01-01
##  7 NUCLEAR  11672     2 2018-01-01
##  8     GAS   1192     2 2018-01-01
##  9   HYDRO   4093     2 2018-01-01
## 10    WIND   1124     2 2018-01-01
## # ... with 2,438 more rows

<强>无论其

从浏览器上下文调用时,它使用XSLT样式表来转换数据以生成该表。我们也可以模仿进程XML。它的速度要快一点,但是你会得到一个宽广的&#34;数据帧与a&#34; long&#34;之一:

library(xml2)
library(xslt)
library(rvest)
library(tidyverse)

doc <- read_xml("http://reports.ieso.ca/public/GenOutputbyFuelHourly/PUB_GenOutputbyFuelHourly.xml")

xsl <- read_xml("http://reports.ieso.ca/docrefs/stylesheet/GenOutputbyFuelHourly_HTML_t1-1.xsl")

xml_xslt(doc, xsl) %>% 
  html_node(xpath=".//table[contains(., 'HYDRO')]") %>% 
  html_table(header=TRUE, fill=TRUE) %>% 
  tbl_df()
## # A tibble: 408 x 9
##          Date  Hour NUCLEAR   GAS HYDRO  WIND SOLAR BIOFUEL `Total Output`
##         <chr> <int>   <int> <int> <int> <int> <int>   <int>          <int>
##  1 2018-01-01     1   11671  1583  4152   992     0       3          18401
##  2 2018-01-01     2   11672  1192  4093  1124     0       1          18082
##  3 2018-01-01     3   11672  1040  4231  1265     0       0          18208
##  4 2018-01-01     4   11669  1041  3895  1369     0       0          17974
##  5 2018-01-01     5   11674  1004  3271  1848     0       0          17797
##  6 2018-01-01     6   11682  1048  3292  2022     0       0          18044
##  7 2018-01-01     7   11682   966  3977  2378     0       1          19004
##  8 2018-01-01     8   11682   741  4311  2542     0       4          19280
##  9 2018-01-01     9   11678   650  4058  2719     2       2          19109
## 10 2018-01-01    10   11682   556  4644  2687    13       2          19584
## # ... with 398 more rows

我(个人)倾向于使用前一种(XML)方法,并努力重构代码以加速转换(我做了#34;蛮力&#34;方式)它是真实的&#34;数据&#34;。

但是,后者有效且速度更快,可能采用您需要的格式而无需进一步转换。

这些都不需要额外的外部依赖,如RSelenium或splashr。

<强>更新

OP关于样式表不在Chrome上的Dev Tools中的评论100%不正确:

enter image description here

在转到网址之前,他们可能没有在Chrome中使用Dev Tools。