如何利用R语言与正则表达式精准提取字符串中的关键信息

2026年02月05日/ 浏览 10

假设你正在分析一批新闻页面的原始HTML代码,目标是从中提取每篇文章的标题、关键词、元描述以及正文内容。虽然现代网络爬虫工具如rvest能直接解析DOM节点,但在某些情况下,比如只获得纯文本快照或处理自定义格式的日志时,正则表达式就成了不可或缺的利器。

首先,让我们构建一个模拟的文本片段:

r
raw_text <- ‘


人工智能如何改变医疗行业



近年来,人工智能技术迅速渗透到医疗健康领域。从影像识别到基因分析,AI正在重塑传统诊疗流程……
(此处省略大量正文内容)
综上所述,技术进步必须与伦理规范同步发展,才能真正实现智慧医疗的可持续未来。



要从中提取标题,我们可以使用如下正则表达式:

r
title_pattern <- '<title>(.*?)</title>'
title_match <- regmatches(raw_text, regexec(title_pattern, raw_text))
title <- if (length(title_match[[1]]) > 1) title_match[[1]][2] else NA

这里的(.*?)是核心捕获组,?表示非贪婪匹配,确保只取第一个闭合标签前的内容。如果不加?,在多个<title>标签存在时可能误匹配到最后一个。

接下来提取关键词。观察content属性内的值,我们设计模式:

r
keyword_pattern <- 'name="keywords"\\s+content="(.*?)"'
keyword_match <- regmatches(raw_text, regexec(keyword_pattern, raw_text, ignore.case = TRUE))
keywords <- if (length(keyword_match[[1]]) > 1) unlist(strsplit(keyword_match[[1]][2], ",\\s*")) else NA

这里加入了ignore.case = TRUE以应对大小写变化,并用strsplit将逗号分隔的关键词拆分为向量,便于后续分析。

对于描述字段,逻辑类似:

r
desc_pattern <- 'name="description"\\s+content="(.*?)"'
desc_match <- regmatches(raw_text, regexec(desc_pattern, raw_text, ignore.case = TRUE))
description <- if (length(desc_match[[1]]) > 1) desc_match[[1]][2] else NA

最难处理的是正文。由于HTML结构复杂,简单正则容易出错。但我们可以通过定位特定类名的div标签来提高准确性:

r
bodypattern <- '(.*?)


body_match <- regmatches(raw_text, regexec(body_pattern, raw_text, dotall = TRUE)) body <- if (length(body_match[[1]]) > 1) body
match[[1]][2] else NA

清理HTML标签

if (!is.na(body)) {
body <- gsub(“<[^>]+>”, “”, body) # 移除所有HTML标签
body <- trimws(body) # 去除首尾空白
}

注意这里使用了dotall = TRUE参数(需加载stringr包或使用perl=TRUE),使得.可以匹配换行符,否则跨行内容会被截断。

整个提取过程可封装为函数:

r
extractarticle <- function(text) {
list(
title = extract
between(text, ‘‘, ‘‘),
keywords = strsplit(extractbetween(text, ‘name=”keywords” content=”‘, ‘”‘), “,\s*”)[[1]],
description = extract
between(text, ‘name=”description” content=”‘, ‘”‘),
body = cleanhtml(extractbetween(text, ‘

‘, ‘

‘))
)
}

extract_between <- function(x, start, end) {
s <- regexpr(paste0(start, “(.*?)”, end), x, perl = TRUE)
if (s == -1) return(NA)
substr(x, s + attr(s, “match.length”) – nchar(end),
s + attr(s, “capture.start”) – 2)
}

clean_html <- function(x) {
if (is.na(x)) return(x)
x <- gsub(“<[^>]+>”, “”, x)
trimws(x)
}

picture loss