从 HTML 正文中提取文本片段(在 .NET 中)

Posted

技术标签:

【中文标题】从 HTML 正文中提取文本片段(在 .NET 中)【英文标题】:Extracting text fragment from a HTML body (in .NET) 【发布时间】:2010-11-17 05:44:34 【问题描述】:

我有一个用户通过富文本编辑器输入的 html 内容,因此它几乎可以是任何内容(除了那些不应该在 body 标签之外的内容,不用担心“head”或 doctype 等)。 此内容的示例:

<h1>Header 1</h1>
<p>Some text here</p><p>Some more text here</p>
<div align=right><a href="x">A link here</a></div><hr />
<h1>Header 2</h1>
<p>Some text here</p><p>Some more text here</p>
<div align=right><a href="x">A link here</a></div><hr />

诀窍是,我只需要提取文本的前 100 个字符(去除 HTML 标记)。我还需要保留换行符,不要打断任何单词。

所以上面的输出会是这样的:

Header 1
Some text here

Some more text here

A link here

Header 2
Some text here

Some

它有 98 个字符,并保留了换行符。到目前为止,我可以实现的是使用 Regex 去除所有 HTML 标签:

Regex.Replace(htmlStr, "<[^>]*>", "")

然后使用正则表达式修剪长度:

Regex.Match(textStr, @"^.1,100\b").Value

我的问题是,如何保留换行符?我得到如下输出:

Header 1
Some text hereSome more text here
A link here
Header 2
Some text hereSome more text

注意到连接的句子了吗?也许有人可以向我展示解决此问题的其他方法。谢谢!

附加信息:我的目的是从一堆 HTML 内容中生成纯文本概要。猜猜这将有助于澄清这个问题。

【问题讨论】:

您是否正在尝试创建一个非常基本的浏览器?我问是因为如果是这样,简单地使用正则表达式(显然)只会让你到目前为止。 @Phairoh 不是浏览器,更像是一个自动概要生成器。 【参考方案1】:

我认为解决这个问题的方法是将它视为一个简单的浏览器。创建一个基本的 Tag 类,用一个 InnerHTML 属性和一个虚拟方法 PrintElement 使其抽象。

接下来,为您关心并从基类继承的每个 HTML 标记创建类。从您的示例来看,您最关心的标签是 h1、p、a 和 hr。实现 PrintElement 方法,使其返回一个字符串,该字符串根据 InnerHTML 正确打印出元素(例如 p 类的 PrintElement 将返回“\n[InnerHTML]\n”)。

接下来,构建一个解析器,它将解析您的 HTML 并确定要创建的对象,然后将这些对象添加到队列中(树会更好,但看起来对您的目的来说不是必需的)。

最后,遍历队列,为每个元素调用 PrintElement 方法。

可能比您计划的要多,但它是一个比简单使用正则表达式更强大的解决方案,如果您决定在未来改变主意并想要显示简单的样式,只需返回并修改您的PrintElement 方法。

【讨论】:

这可能是一个更好的解决方案 - 如果您按应有的方式处理 p 和 div 标签(块级元素),那么用新行替换应该会很好地工作。 哇,肯定比我分配的要多得多。如前所述,我的最终目的是提取前 X 个字符并显示为纯文本而不破坏任何单词,并具有相应的换行符作为 HTML 内容在浏览器中的呈现方式。但是感谢 Phairoh 提出了一些我没想到的东西。 +1 :)【参考方案2】:

对于信息,使用正则表达式剥离 html 是......充满了微妙的问题。 HTML Agility Pack 可能更健壮,但仍然受到字词的影响:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string text = doc.DocumentNode.InnerText;

【讨论】:

我试过敏捷包。我不太担心剥离 HTML 标签,因为内容和布局不太花哨。就像你说的那样,话语仍然在流血。【参考方案3】:

一种方法是分三步剥离 html:

Regex.Replace(htmlStr, "<[^/>]*>", "") // don't strip </.*>
Regex.Replace(htmlStr, "</p>", "\r\n") // all paragraph ends are replaced w/ new line
Regex.Replace(htmlStr, "<[^>]*>", "") // replace remaining </.*>

【讨论】:

如果段落标签有一个尾随换行符,我必须确保没有引入额外的换行符。我还必须注意任何块元素,如 DIV 和 HR 等。这个列表还在继续。【参考方案4】:

好吧,虽然没有理想的解决方案,但我需要关闭它。由于我的应用程序中使用的 HTML 标记非常常见(没有表格、列表等),几乎没有嵌套,所以我所做的是在用户输入后保存 HTML 片段之前预先格式化它们。

删除所有换行符 为所有块标签添加换行前缀(例如 div、p、hr、h1/2/3/4 等)

在我提取它们以显示为纯文本之前,使用正则表达式删除 html 标记并保留换行符。几乎没有任何火箭科学,但对我有用。

【讨论】:

以上是关于从 HTML 正文中提取文本片段(在 .NET 中)的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中提取和清理 HTML 正文文本的最快、最无错误的方法是啥?

从网站中提取正文文本,例如仅提取文章标题和文本而不是站点中的所有文本

php从邮件正文中提取文本/纯文本

从单个按钮从多个片段中提取数据

基于文本密度的新闻正文抽取方法之Python实现

如何从单个文本文件中提取不同的文章?