用于提取 HTML 正文内容的正则表达式

Posted

技术标签:

【中文标题】用于提取 HTML 正文内容的正则表达式【英文标题】:Regular Expression to Extract HTML Body Content 【发布时间】:2010-09-26 06:15:42 【问题描述】:

我正在寻找一个正则表达式,它可以让我从 Xhtml 文档的 body 标记之间提取 HTML 内容。

我需要解析的 XHTML 将是非常简单的文件,例如,我不必担心 javascript 内容或<![CDATA[ 标签。

下面是我必须解析的 HTML 文件的预期结构。因为我确切地知道我将不得不使用的 HTML 文件的所有内容,所以这个 HTML sn-p 几乎涵盖了我的整个用例。如果我能得到一个正则表达式来提取这个例子的主体,我会很高兴。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>
    </title>
  </head>
  <body contenteditable="true">
    <p>
      Example paragraph content
    </p>
    <p>
      &nbsp;
    </p>
    <p>
      <br />
      &nbsp;
    </p>
    <h1>Header 1</h1>
  </body>
</html>

从概念上讲,我一直在尝试构建一个匹配除内部正文内容之外的所有内容的正则表达式字符串。有了这个,我将使用 C# Regex.Split() 方法来获取正文内容。我认为这个正则表达式:

((.|\n)*<body (.)*>)|((</body>(*|\n)*)

...可以解决问题,但它似乎根本不适用于我在 RegexBuddy 中的测试内容。

【问题讨论】:

Split() 是这个工作的错误工具。只需使用Regex.Match(subject, "(?s)&lt;body[^&gt;]*&gt;(.*)&lt;/body&gt;").Groups[1].Value 【参考方案1】:

匹配第一个正文标签:&lt;\s*body.*?&gt;

匹配最后一个正文标签:&lt;\s*/\s*body.*?&gt;

(注意:我们考虑了标签中间的空格,顺便说一句,这是完全有效的标记)

像这样将它们组合在一起,您将获得介于两者之间的所有内容,包括正文标签:&lt;\s*body.*?&gt;.*?&lt;\s*/\s*body.*?&gt;。并确保您使用的是Singleline 模式,该模式将忽略换行符。

这适用于 VB.NET,希望其他人也适用!

【讨论】:

【参考方案2】:
/<body[^>]*>(.*)</body>/s

替换为

\1

【讨论】:

这应该匹配整个文档并将正文放入\3。这样你就知道如果不匹配整个文档说明当前文档的格式还有别的需要考虑,可以抛出错误。 我知道这是一个非常古老的帖子,但是该死.. 我喜欢这个答案,不得不让人们知道它。 请注意,在 Perl 正则表达式和 Java 中,您必须打开 s 标志以强制内部 (.*) 匹配换行符,这通常是您想要的。在我看来,也没有必要进行开始或结束分组 - 更简单的答案是 /&lt;body[^&gt;]*&gt;(.*)&lt;/body&gt;/s 并使用第 1 组。 @aarestad 谢谢,我已经编辑过,你说得对——我的正则表达式技能在那个时候有点绿色:)【参考方案3】:
String toMatch="aaaaaaaaaaabcxx sldjfkvnlkfd <body>i m avinash</body>";
Pattern pattern=Pattern.compile(".*?<body.*?>(.*?)</body>.*?");
Matcher matcher=pattern.matcher(toMatch);
if(matcher.matches()) 
    System.out.println(matcher.group(1));

【讨论】:

【参考方案4】:

这行得通吗?

((?:.(?!<body[^>]*>))+.<body[^>]*>)|(</body\>.+)

当然,您需要添加必要的\s,以便考虑&lt; body ...&gt;(带空格的元素),如:

((?:.(?!<\s*body[^>]*>))+.<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)

再想一想,我不知道为什么我需要一个消极的前瞻......这也应该工作(对于格式良好的 xhtml 文档):

(.*<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)

【讨论】:

嗯,看起来是一个很好的例子来证明 REs 不应该用于(未知的)HTML: 是有效的...... :- ) PhiLho,你错了,它不是有效的 XHTML。 ">" 必须转义为 ">"是 XML 格式良好的。然而,Web 浏览器使用各种 hack 来读取损坏的 HTML/XHTML。包含 JavaScript 内容的页面通常不是 XML 格式正确的,除非它们被放入 CDATA。 谢谢。您能否再描述一下如何在 C# 中将其与 Regex 库一起使用。从 html 文档字符串返回所需内容的语句 @enduser 十二年后,我相信这个答案更多地是关于使用的正则表达式而不是它的 C# 用法。对于后者,我将遵循 c-sharpcorner.com/article/c-sharp-regex-examples 中的一个示例。【参考方案5】:

使用 XML 解析器比使用正则表达式更容易解析 XHTML。我知道这不是您要的,但是 XML 解析器将能够快速导航到正文节点并将其内容返回给您,而不会出现正则表达式给您带来的任何标签映射问题。

编辑: 回应这里的评论; XML 解析器太慢了。

有两种 XML 解析器,一种叫做 DOM,它又大又重,而且简单友好,它在你可以做任何事情之前从文档中构建一棵树。另一种称为 SAX,速度快、重量轻、工作量大,它按顺序读取文件。您将希望 SAX 找到 Body 标记。

DOM 方法适用于多种用途,拉取标签并找出谁是孩子。 SAX 解析器按顺序读取文件并快速获取您需要的信息。正则表达式不会比 SAX 解析器快,因为它们都只是遍历文件和模式匹配,除了正则表达式在找到正文标记后不会退出,因为正则表达式没有内置XML的知识。事实上,您的 SAX 解析器可能使用小块正则表达式来查找每个标记。

【讨论】:

没有理由重新发明***。如果是 XHTML,那就是 XML,而 XML 解析器就是完成这项工作的工具。 +1 这是我厌倦的第一个解决方案,但它似乎运行得很慢。我认为 RegEx 会更快。 XML 解析器有两种,一种叫做DOM,它又大又重又简单友好,它在你做任何事情之前就从文档中构建出一棵树。另一种称为 SAX,速度快、重量轻、工作量大,它按顺序读取文件。您将希望 SAX 找到 Body 标记。 这对于解析器来说是一个非常简单的工作,它真的不应该很慢 我最初使用 .NET 的 System.Xml.XmlDocument 类进行了尝试,如果这可以解释任何缓慢的话。 ——马修·拉斯顿【参考方案6】:

你为什么不能把它分开

</0,1body[^>]*> 

然后取第二个字符串?我相信它会比寻找一个巨大的正则表达式要快得多。

【讨论】:

也就是说,如果你解决了这个问题,你的方法可能会更简单。 :) 好吧,在您发布评论并编辑此答案之前,我刚刚注意到它:P 我实际上没有足够的积分来编辑...一定是其他人。

以上是关于用于提取 HTML 正文内容的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

Python 正则表达式不适用于 Gmail 正文

用于查找 HTML 标签及其内容的正则表达式的否定 - java

jmeter_正则表达式提取器

正则表达式() [] {}区别

正则表达式 提取 html 标签的内容

使用正则表达式删除 html 实体并提取文本内容