【问题标题】:R scrape html table and extract background colorR刮html表并提取背景颜色
【发布时间】:2018-06-20 09:09:35
【问题描述】:

我正在尝试从该页面的维基百科表格中抓取一些数据: https://en.wikipedia.org/wiki/Results_of_the_Indian_general_election,_2014 我对这张桌子很感兴趣: 2014年印度大选总结

我还想从表格中提取派对颜色。 到目前为止,这是我尝试过的:

library("rvest")
url <- 
"https://en.wikipedia.org/wiki/Results_of_the_Indian_general_election,_2014"

electionstats <- read_html(url)
results <- html_nodes(electionstats, xpath='//*[@id="mw-content-text"]/div/table[79]') %>% html_table(fill = T)

party_colors <- electionstats %>% 
html_nodes(xpath='//*[@id="mw-content-text"]/div/table[3]') %>% 
html_table(fill = T)

打印出party_colors 不显示任何关于颜色的信息

所以,我尝试了:

party_colors <- electionstats %>% html_nodes(xpath='//*[@id="mw-content-text"]/div/table[3]') %>%  
html_nodes('tr')

现在如果我打印出party_colors,我会得到:

[1] <tr style="background-color:#E9E9E9">\n<th style="text-align:left;vertical-align:bottom;" rowspan="2"></th>\n<th style="text-align:left; ...
[2] <tr style="background-color:#E9E9E9">\n<th style="text-align:center;">No.</th>\n<th style="text-align:center;">+/-</th>\n<th style="text ...
[3] <tr>\n<td style="background-color:#FF9933"></td>\n<td style="text-align:left;"><a href="/wiki/Bharatiya_Janata_Party" title="Bharatiya J ...
[4] <tr>\n<td style="background-color:#00BFFF"></td>\n<td style="text-align:left;"><a href="/wiki/Indian_National_Congress" title="Indian Na ...
[5] <tr>\n<td style="background-color:#009900"></td>\n<td style="text-align:left;"><a href="/wiki/All_India_Anna_Dravida_Munnetra_Kazhagam"  ...

等等……

但是,现在,我不知道如何从这些数据中提取颜色。我无法将上面的输出转换为 html_table:

html_table(fill = T)

我得到错误:

Error: html_name(x) == "table" is not TRUE

我还尝试了 html_attrs 的各种选项,但我不知道我应该传递的正确属性是什么。

我什至尝试过 SelectorGadget 来尝试找出属性,但如果我选择相关表格的第一列,SelectorGadget 只会显示“td”。

【问题讨论】:

  • FWIW,我无法重现您的代码:results 是一个空列表。我想知道这是否取决于 XPath。似乎在没有id 的情况下在维基百科页面上选择一个表格不是超级可重复的,但我想你真的别无选择:/
  • 感谢指出....在美化条目时,我无意中删除了xpath中的连字符。现已修复。

标签: r web-scraping rvest


【解决方案1】:

我会像您一样获取表格,然后将颜色属性添加为列。 wikitable 可排序类适用于许多页面,因此获取第一个并删除第 1 行中的第二个标题。

electionstats <- read_html(url) 
x <- html_nodes(electionstats, xpath='//table[@class="wikitable sortable"]')[[1]] %>% 
      html_table(fill=TRUE)
# paste names from 2nd row header and then remove
names(x)[6:14] <- paste(names(x)[6:14], x[1,6:14])
x <- x[-1,]

颜色位于第一个 tr/td 标签中,您可以将其添加到空列 1 或 3(参见 str(x)

names(x)[3] <- "Color"
x$Color <- html_nodes(electionstats, xpath='//table[@class="wikitable sortable"][1]/tr/td[1]') %>% 
            html_attr("style") %>% gsub("background-color:", "", .)
## drop table footer, extra columns
x <- x[1:83, 2:14]   
head(x)
                                     Party   Color Alliance Abbr. Candidates No. Candidates +/- Candidates %
2                   Bharatiya Janata Party #FF9933      NDA   BJP            428             -5       78.82%
3                 Indian National Congress #00BFFF      UPA   INC            464             24       85.45%
4 All India Anna Dravida Munnetra Kazhagam #009900           ADMK             40             17        7.37%
5             All India Trinamool Congress #00FF00           AITC            131             96       24.13%
6                          Biju Janata Dal #006400            BJD             21              3        3.87%
7                                Shiv Sena #E3882D      NDA   SHS             24             11       10.68%

【讨论】:

  • 我猜 xpath='//table[@class="wikitable sortable"][1]/tr/td[1] 中的 /tr/td[1] 是我要找的.这行得通!谢谢!
【解决方案2】:

您的 xml_nodeset 似乎包含 trtd 节点。

同时处理trs和tds,转换成数据帧:

party_colors_tr <- electionstats %>% html_nodes(xpath='//*[@id="mw-content-text"]/div/table[3]') %>% html_nodes('tr')
trs <- bind_rows(lapply(xml_attrs(party_colors_tr), function(x) data.frame(as.list(x), stringsAsFactors=FALSE)))
party_colors_td <- electionstats %>% html_nodes(xpath='//*[@id="mw-content-text"]/div/table[3]') %>% html_nodes('tr') %>% html_nodes('td')
tds <- bind_rows(lapply(xml_attrs(party_colors_td), function(x) data.frame(as.list(x), stringsAsFactors=FALSE)))

编写从数据框中提取样式的函数:

library(stringi)
list_styles <- function(nodes_frame) {
    get_cols <- function(x) { stri_detect_fixed(x, 'background-color') }
    has_style <- which(lapply(nodes_frame$style, get_cols) == TRUE)
    res <- strsplit(nodes_frame[has_style,]$style, ':')
    return(res)
}

创建提取样式的数据框:

l_trs <- list_styles(trs)
df_trs <- data.frame(do.call('rbind', l_trs)[,1], do.call('rbind', l_trs)[,2])
names(df_trs) <- c('style', 'color')

l_tds <- list_styles(tds)
df_tds <- data.frame(do.call('rbind', l_tds)[,1], do.call('rbind', l_tds)[,2])
names(df_tds) <- c('style', 'color')

结合 trs 和 tds 框架:

final_style_frame <- do.call('rbind', list(df_trs, df_tds))

这里是前 20 行:

final_style_frame[1:20,]

【讨论】:

  • 谢谢!在这里,我确信 R 是如此简单:) 不过,有一个解决方案很好。这是实现我想要的最有效的方法吗?还有其他的包/方法吗?
  • 绝对不是最有效的方法。如果我找到更好的东西,我会告诉你的。
猜你喜欢
  • 2019-08-30
  • 2019-03-31
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
  • 2015-04-05
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
相关资源
最近更新 更多