如何将 rvest 应用于 HTML 的数据框列以制作一列提取的大胆词
How to apply rvest to a dataframe column of HTML to make a column of extracted emboldened words
我有一个数据框,其中一列 - raw - 是 HTML:
other column
raw
First row
<p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p>
Second row
<div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div>
我想从原始列中构建一些新列。我想要每个通用样式属性(粗体、斜体、下划线等)一列 - 例如,is_bold 列中的每个条目要么是“粗体”,要么只是空白。所以我最终想要的输出是这样的:
other column
raw
is_bold
is_italic
First row
<p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p>
italic
Second row
<div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div>
bold
italic
如上例所示,我的几个 HTML 段落中有一些文本采用某些样式,而另一些则没有。例如。我的第一行有两个字符 ("55") 是粗体,其余的不是,而整个段落是斜体 - 所以,比如说,至少 50% 的 text HTML 是粗体,我想将该行标记为粗体。
所以,为了实现这个期望的输出,我想提取任何粗体文本,计算其组合长度(即使粗体部分分布在段落的不同部分),除以总长度段落,如果这个数字超过 0.5,则将该行标记为粗体。所以我的问题是:
- 如何在数据框设置中实现它?对于 html 的单个字符串而不是数据帧,以下代码有效:
html <- "some html here"
bold_parts <- html %>% html_nodes("b, strong") %>% html_text()
因此,将此应用于我的数据框列,有人可以帮我弄清楚如何修改下面的代码以将任何大胆的词提取到名为 bold_words[=51 的新列中=]?从那里,我可以计算这些粗体字的长度并将其除以 raw 列的长度。
dataframe <- dataframe %>%
rowwise() %>%
mutate(
bold_words = read_html(raw) %>%
html_nodes("b, strong) %>%
html_text()
)
一旦它起作用,它应该适用于 <b>, <strong>, <i>, <em>, and <u>
定义的样式。
但是,我不确定如何将它应用于 HTML,就像第 2 行中的那样 - 而不是 <b> or <i> or <u>
,外观由 "font-style:italic", "text-decoration:underline" and "font-weight:bold"
决定。我可以使用正则表达式在这些部分拆分它,但我宁愿解析 HTML.
如果有人发现更好的方法来做这些,我们将不胜感激,即使这意味着使用完全不同的方法。
谢谢
您可以使用带有 * contains 运算符的属性选择器来指定包含粗体的样式属性。
下面显示了创建一个粗略的通用函数,您可以将 css 模式和所需的列文本传递给给定的输出列。显示的是 is_bold
和 is_italic
.
的模式
TODO:您可能想要添加一些错误处理,例如如果 HTML 解析错误。
library(tidyverse)
library(rvest)
df <- data.frame(
other= c("First Row", "Second Row"),
raw = c(
'<p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p>',
'<div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div>'
)
)
is_pattern <- function(i, css_selector, return_text) {
page <- read_html(i)
all_text <- nchar(page %>% html_text())
pattern_text <- sum(nchar(page %>% html_nodes(css_selector) %>% html_text()))
flag <- ifelse(length(all_text) == 0 | length(pattern_text) == 0, F, (pattern_text / all_text) >= .5)
return(ifelse(flag, return_text, ''))
}
df$`is_bold` <- lapply(df$raw, is_pattern, 'b, strong, [style*="font-weight:bold"]', 'bold')
变异示例:
is_pattern <- Vectorize(is_pattern)
df <- df %>%
mutate(
is_bold = is_pattern(raw, 'b, strong, [style*="font-weight:bold"]', 'bold'),
is_italic = is_pattern(raw, 'em, i, [style*="font-style:italic"]', 'italic'),
)
我从@r2evans an answer 那里注意到我需要对函数进行向量化。
我有一个数据框,其中一列 - raw - 是 HTML:
other column | raw |
---|---|
First row | <p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p> |
Second row | <div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div> |
我想从原始列中构建一些新列。我想要每个通用样式属性(粗体、斜体、下划线等)一列 - 例如,is_bold 列中的每个条目要么是“粗体”,要么只是空白。所以我最终想要的输出是这样的:
other column | raw | is_bold | is_italic |
---|---|---|---|
First row | <p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p> |
italic | |
Second row | <div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div> |
bold | italic |
如上例所示,我的几个 HTML 段落中有一些文本采用某些样式,而另一些则没有。例如。我的第一行有两个字符 ("55") 是粗体,其余的不是,而整个段落是斜体 - 所以,比如说,至少 50% 的 text HTML 是粗体,我想将该行标记为粗体。
所以,为了实现这个期望的输出,我想提取任何粗体文本,计算其组合长度(即使粗体部分分布在段落的不同部分),除以总长度段落,如果这个数字超过 0.5,则将该行标记为粗体。所以我的问题是:
- 如何在数据框设置中实现它?对于 html 的单个字符串而不是数据帧,以下代码有效:
html <- "some html here"
bold_parts <- html %>% html_nodes("b, strong") %>% html_text()
因此,将此应用于我的数据框列,有人可以帮我弄清楚如何修改下面的代码以将任何大胆的词提取到名为 bold_words[=51 的新列中=]?从那里,我可以计算这些粗体字的长度并将其除以 raw 列的长度。
dataframe <- dataframe %>%
rowwise() %>%
mutate(
bold_words = read_html(raw) %>%
html_nodes("b, strong) %>%
html_text()
)
一旦它起作用,它应该适用于
<b>, <strong>, <i>, <em>, and <u>
定义的样式。 但是,我不确定如何将它应用于 HTML,就像第 2 行中的那样 - 而不是<b> or <i> or <u>
,外观由"font-style:italic", "text-decoration:underline" and "font-weight:bold"
决定。我可以使用正则表达式在这些部分拆分它,但我宁愿解析 HTML.如果有人发现更好的方法来做这些,我们将不胜感激,即使这意味着使用完全不同的方法。
谢谢
您可以使用带有 * contains 运算符的属性选择器来指定包含粗体的样式属性。
下面显示了创建一个粗略的通用函数,您可以将 css 模式和所需的列文本传递给给定的输出列。显示的是 is_bold
和 is_italic
.
TODO:您可能想要添加一些错误处理,例如如果 HTML 解析错误。
library(tidyverse)
library(rvest)
df <- data.frame(
other= c("First Row", "Second Row"),
raw = c(
'<p id="PARA339" style="TEXT-ALIGN: left; MARGIN: 0pt; LINE-HEIGHT: 1.25"><font style="FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman, Times, serif"><i>We had a net loss of .</i><i><b>55</b></i><i> million for the year ended December 31, 201</i><i>6</i><i> and have an accumulated deficit of $</i><i>61.5</i><i> million as of December 31, 201</i><i>6</i><i>. To achieve sustainable profitability, we must generate increased revenue.</i></font></p>',
'<div style="line-height:174%;text-align:left;font-size:9pt;"><font style="font-family:inherit;font-size:9pt;font-style:italic;font-weight:bold;">We have a history of losses, and we cannot assure you that we will achieve profitability.</font></div>'
)
)
is_pattern <- function(i, css_selector, return_text) {
page <- read_html(i)
all_text <- nchar(page %>% html_text())
pattern_text <- sum(nchar(page %>% html_nodes(css_selector) %>% html_text()))
flag <- ifelse(length(all_text) == 0 | length(pattern_text) == 0, F, (pattern_text / all_text) >= .5)
return(ifelse(flag, return_text, ''))
}
df$`is_bold` <- lapply(df$raw, is_pattern, 'b, strong, [style*="font-weight:bold"]', 'bold')
变异示例:
is_pattern <- Vectorize(is_pattern)
df <- df %>%
mutate(
is_bold = is_pattern(raw, 'b, strong, [style*="font-weight:bold"]', 'bold'),
is_italic = is_pattern(raw, 'em, i, [style*="font-style:italic"]', 'italic'),
)
我从@r2evans an answer 那里注意到我需要对函数进行向量化。