首页 > 解决方案 > 如何使用 R 解析 html 文本?

问题描述

我有一个表格的示例 html 代码

<td class="rgGroupCol">&nbsp;</td>
<td>Hope, Bob</td>
<td>7</td>
<td style="background-color:#BCD4E8;">0</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#ECE1BA;">7</td>
<td style="background-color:#F3ECCC;">7</td>
<td style="background-color:#F3ECCC;">0</td>

<td class="rgGroupCol">&nbsp;</td>
<td>Tan, Sally </td>
<td>76</td>
<td style="background-color:#BCD4E8;">0</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#ECE1BA;">76</td><td style="background-color:#F3ECCC;">23</td>
<td style="background-color:#F3ECCC;">53</td>

<td class="rgGroupCol">&nbsp;</td>
<td>Smith, Mark</td><td>2</td>
<td style="background-color:#BCD4E8;">0</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td>
<td style="background-color:#ECE1BA;">2</td>
<td style="background-color:#F3ECCC;">0</td>
<td style="background-color:#F3ECCC;">2</td>

我想解析其中的文本<td></td>并将其转换为表格。每个观察都以名称开头,然后是 11 列信息(数字),如下所示

X1          X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 
Hope, Bob    7  0  0 0%  0 0%  0 0%  7   7   0 
Tan, Sally  76  0  0 0%  0 0%  0 0% 76  23  53
Smith, Mark  2  0  0 0%  0 0%  0 0%  2   0   2

我试过使用html_table,但它无法读取文本。
我曾尝试使用 datapasta 从网站复制和粘贴,但没有成功。
我也尝试过使用这些代码,但无法真正完成上述输出

test <- read_delim("eval num.txt", delim = "\n", col_names = FALSE)
test$X1 <- str_match(test$X1, "<td>[a-zA-Z0-9%,. ]+</td>")

请启发我。谢谢!

标签: htmlr

解决方案


您的第一个代码块不是有效的 HTML 表格,因此您将遇到麻烦。它需要被包裹起来<table> ... </table>,每一行都需要被包裹起来<tr>...</tr>。我在您的示例中看不到这些标签中的任何一个。

我可以手动将它们放入,假设您的样本的每一行都是表格中的一行。这给出了 HTML 代码

<table> 
<tr><td class="rgGroupCol">&nbsp;</td><td>Hope, Bob</td><td>7</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">7</td><td style="background-color:#F3ECCC;">7</td><td style="background-color:#F3ECCC;">0</td></tr>
                       <tr><td class="rgGroupCol">&nbsp;</td><td>Tan, Sally </td><td>76</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">76</td><td style="background-color:#F3ECCC;">23</td><td style="background-color:#F3ECCC;">53</td></tr>
                       <tr> <td class="rgGroupCol">&nbsp;</td><td>Smith, Mark</td><td>2</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">2</td><td style="background-color:#F3ECCC;">0</td><td style="background-color:#F3ECCC;">2</td></tr> 
</table>

然后,如果您将该文本放入字符串中,rvest包可以将其转换为数据框。例如,

sample <- '<table><tr><td class="rgGroupCol">&nbsp;</td><td>Hope, Bob</td><td>7</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">7</td><td style="background-color:#F3ECCC;">7</td><td style="background-color:#F3ECCC;">0</td></tr>
                       <tr><td class="rgGroupCol">&nbsp;</td><td>Tan, Sally </td><td>76</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">76</td><td style="background-color:#F3ECCC;">23</td><td style="background-color:#F3ECCC;">53</td></tr>
                       <tr> <td class="rgGroupCol">&nbsp;</td><td>Smith, Mark</td><td>2</td><td style="background-color:#BCD4E8;">0</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#D2DEE8;"><span class="details_gridpercentage">0</span>0%</td><td style="background-color:#ECE1BA;">2</td><td style="background-color:#F3ECCC;">0</td><td style="background-color:#F3ECCC;">2</td></tr> </table>'

library(rvest)
sample1 <- minimal_html(sample)
sample1 %>%
  html_node("table") %>%
  html_table()

这打印表格

  X1          X2 X3 X4  X5  X6  X7 X8 X9 X10
1 NA   Hope, Bob  7  0 00% 00% 00%  7  7   0
2 NA  Tan, Sally 76  0 00% 00% 00% 76 23  53
3 NA Smith, Mark  2  0 00% 00% 00%  2  0   2

它只找到 8 列数据,这就是我在 HTML 中看到的全部内容;我不知道为什么你认为应该有 11 个。

编辑添加:

根据评论,您不想解析 HTML,您想删除所有 HTML 标签。这段代码做到了:

notags <- gsub("[<][^<>]*[>]", " ", sample)

这使用正则表达式:[<]表示单个字符"<"。您可能可以 <不使用方括号,但我总是忘记哪些字符在正则表达式中具有特殊含义,所以这可能不起作用。

然后表示除or之外的[^<>]任何字符,并且表示其中的“零个或多个”。最后,我们在括号中结束。"<"">"*>

所以gsub用一个空白替换任何看起来像 HTML 标记的东西。我不知道 HTML 的所有规则是否知道它是否会做错事,但它应该处理大多数情况。

删除标签后,您可以使用 read.table 读取新字符串:

read.table(text = notags)

并使用与sample上面相同的方法,您将得到以下结果:

      V1     V2    V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
1 &nbsp;  Hope,   Bob  7  0  0 0%  0 0%   0  0%   7   7   0
2 &nbsp;   Tan, Sally 76  0  0 0%  0 0%   0  0%  76  23  53
3 &nbsp; Smith,  Mark  2  0  0 0%  0 0%   0  0%   2   0   2

这似乎与您想要的非常接近;我会把最后一点清理工作留给你。


推荐阅读