httr GET 函数读取 table

httr GET function read table

我想抓取这个 website,并从 table 中获取数据。

我使用包httr中的GET,代码如下:

url <- 'http://datacenter.mep.gov.cn/report/water/water.jsp?'
year <- 2016
wissue <- 2

res <- GET(url,
           query = list(year = year,
                        wissue = wissue))


resC <- content(res, as = 'text', encoding = 'utf-8')

但我得到的不是 json 字符串,而是一些非常奇怪的东西,如下所示:

"\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<html>\r\n\t<head>\r\n\t\t<title>中华人民共和国环境保护部--政府网站数据中心</title>\r\n\t\t<meta http-equiv=\"content-type\" content=\"text/html;

不知道有没有办法解析这种格式?

rowspan 属性将使处理此 table 变得非常有趣。您有几个选择,其中两个是:

  1. 使用fill=TRUE在目标<table>上使用html_table()并对结果数据帧进行手术
  2. <tr> 级别对其进行攻击并从头开始构建数据框

这个答案是后者。

library(rvest)
library(purrr)

首先,我们以可以对以下对象执行 XML/HTML 手术的形式获取内容:

content(res, as = 'text', encoding = 'utf-8') %>% 
  read_html() -> pg

接下来,我们使用报告定位并提取 table 节点:

tab <- html_nodes(pg, "table#report1") 

这是一个棘手的问题。我们首先定位所有具有 @rowspan 属性但没有 <td> 具有 @colspan 属性的元素的 <tr> 元素:

html_nodes(tab, xpath=".//tr[td[not(@colspan) and @rowspan]]") %>% 

接下来,我们逐一处理:

  map_df(function(x) {

我们得到 <tr> 跨越的行数:

    html_nodes(x, xpath=".//td[@rowspan]") %>% 
      html_attr("rowspan") %>% 
      as.numeric() -> row_ct

找到所有兄弟 <tr> 元素并将集合减少到此 <tr> 中的剩余元素 "block":

    rows <- html_nodes(x, xpath=".//following-sibling::tr")
    rows <- rows[1:(row_ct-1)] 

从第一个块行制作数据框

    html_nodes(x, xpath=".//td") %>% 
      html_text() %>% 
      setNames(sprintf("X%d", 1:13)) %>% 
      as.list() %>% 
      flatten_df() -> first

遍历所有已过滤的同级行并执行相同操作,为填充跨列留出空间:

    map_df(rows, ~html_nodes(., xpath=".//td") %>% 
             html_text() %>% 
             setNames(c("X1", "X2", sprintf("X%d", 4:13))) %>% 
             as.list()) %>% 
      mutate(X3=first$X3) %>% 
      select(X1, X2, X3, everything()) -> rest

    bind_rows(first, rest)

  }) -> h2o_df

dplyr::glimpse(h2o_df)

我无法粘贴它的输出,因为 SO 的 javascript 文本过滤器非常脑残,它认为 post 是垃圾邮件只是 b/c 它有汉字字符。

这是连续块中的所有代码:

tab <- html_nodes(pg, "table#report1") 

html_nodes(tab, xpath=".//tr[td[not(@colspan) and @rowspan]]") %>% 
  map_df(function(x) {

    html_nodes(x, xpath=".//td[@rowspan]") %>% 
      html_attr("rowspan") %>% 
      as.numeric() -> row_ct

    rows <- html_nodes(x, xpath=".//following-sibling::tr")
    rows <- rows[1:(row_ct-1)] 

    html_nodes(x, xpath=".//td") %>% 
      html_text() %>% 
      setNames(sprintf("X%d", 1:13)) %>% 
      as.list() %>% 
      flatten_df() -> first

    map_df(rows, ~html_nodes(., xpath=".//td") %>% 
             html_text() %>% 
             setNames(c("X1", "X2", sprintf("X%d", 4:13))) %>% 
             as.list()) %>% 
      mutate(X3=first$X3) %>% 
      select(X1, X2, X3, everything()) -> rest

    bind_rows(first, rest)

  }) -> h2o_df