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 变得非常有趣。您有几个选择,其中两个是:
- 使用
fill=TRUE
在目标<table>
上使用html_table()
并对结果数据帧进行手术
- 在
<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
我想抓取这个 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 变得非常有趣。您有几个选择,其中两个是:
- 使用
fill=TRUE
在目标<table>
上使用html_table()
并对结果数据帧进行手术 - 在
<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