使用C#正则表达式删除HTML标记

137 html c# regex parsing

如何使用C#正则表达式替换/删除所有HTML标记,包括尖括号?有人可以帮我提供代码吗?

Dan*_*ner 149

如前所述,您不应使用正则表达式来处理XML或HTML文档.它们在HTML和XML文档中表现不佳,因为无法以一般方式表达嵌套结构.

您可以使用以下内容.

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);
Run Code Online (Sandbox Code Playgroud)

这适用于大多数情况,但有些情况(例如CDATA包含尖括号),这将无法按预期工作.

  • 这是一个天真的实现..也就是说,<div id ="x <4>">是不幸的,有效的html.处理大多数理智的案件虽然.. (13认同)
  • @Cipher,为什么你认为贪婪是个问题?假设匹配从有效HTML标记的开头开始,它将永远不会超出该标记的末尾.这就是[^>]的用途. (13认同)
  • 如上所述,我知道在某些情况下这个表达式会失败.我甚至不确定一般情况是否可以由任何正则表达式处理而没有错误. (8认同)

Jas*_*rue 78

正确的答案是不要那样做,使用HTML Agility Pack.

编辑添加:

为了无耻地从jesse的下面的评论中窃取,并且为了避免被指责在这段时间之后没有充分回答这个问题,这里有一个简单,可靠的片段,使用HTML Agility Pack,即使是最不完美的,形式多变的HTML:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());
Run Code Online (Sandbox Code Playgroud)

使用正则表达式解析HTML几乎没有什么可辩护的案例,因为即使在非传统的正则表达式引擎中,如果没有上下文感知也无法正确解析HTML.您可以通过RegEx获得部分途径,但您需要进行人工验证.

Html Agility Pack可以为您提供一个强大的解决方案,可以减少手动修复由于天真地将HTML视为无上下文语法而导致的像差的需要.

正则表达式可能会在大多数情况下使您获得大部分时间,但在非常常见的情况下会失败.如果你能找到一个比HTML Agility Pack更好/更快的解析器,那就去吧,但请不要让世界受到更多破坏的HTML hackery.

  • HTML Agility Pack不是与使用HTML相关的所有内容的答案(例如,如果您只想使用HTML代码的片段,那该怎么办?). (27认同)
  • 这不是意见问题.正则表达式可能会在大多数情况下使您获得大部分时间,但在非常常见的情况下会失败.如果你能找到一个比HTML Agility Pack更好/更快的解析器,那就去吧,但请不要让世界受到更多破坏的HTML hackery. (20认同)
  • 它适用于HTML片段,并且它是原始海报描述的场景的最佳选择.另一方面,正则表达式只能使用理想化的HTML,并且会破坏完全有效的HTML,因为HTML的语法不规则.如果他使用Ruby,我仍然会建议使用nokogiri或hpricot,或者是针对Python的beautifulsoup.最好将HTML视为HTML,而不是任何没有语法的任意文本流. (7认同)
  • 这不是正确的答案.同意@PropellerHead. (2认同)
  • 如果不解析HTML,则无法可靠地正确识别HTML标记.你了解HTML的所有语法吗?看到邪恶的黑客得到其他答案所暗示的"非常接近",并告诉我为什么你想要保持这一点.低估我,因为对你的样本输入进行hacky快速尝试不会使你的解决方案正确.我偶尔会使用正则表达式从HTML内容生成报告,或使用&gt;上的否定匹配修复一些CSS引用 为了限制错误的机会,但我们做了额外的验证; 这不是一般目的. (2认同)

Ala*_*ore 38

问题太广泛,无法明确回答.您是在谈论从真实HTML文档中删除所有标记,例如网页?如果是这样,你必须:

  • 删除<!DOCTYPE声明或<?xml prolog(如果存在)
  • 删除所有SGML评论
  • 删除整个HEAD元素
  • 删除所有SCRIPT和STYLE元素
  • 用Grabthar知道FORM和TABLE元素
  • 删除剩余的标签
  • 从CDATA部分删除<![CDATA [和]]>序列,但保留其内容

这只是我的头脑 - 我相信还有更多.一旦你完成了所有这些,你最终会在某些地方一起运行单词,句子和段落,而在其他地方运行大块无用的空白.

但是,假设您只使用一个片段,并且只需删除所有标记即可逃脱,这里是我将使用的正则表达式:

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"
Run Code Online (Sandbox Code Playgroud)

在他们自己的替代品中匹配单引号和双引号字符串足以处理属性值中的尖括号问题.我没有看到任何需要明确匹配标签内的属性名称和其他内容,如Ryan的答案中的正则表达式; 第一个替代方案处理所有这些.

如果你想知道那些(?>...)结构,他们就是原子组.它们使正则表达式更有效率,但更重要的是,它们可以防止失控的回溯,这是你应该经常注意的,当你混合使用交替和嵌套量词时,就像我一样.我真的不认为这会是一个问题,但我知道如果我不提它,别人会.;-)

当然,这个正则表达式并不完美,但它可能就像你需要的一样好.

  • 这是迄今为止最好的答案。您回答发帖者的问题并解释为什么正则表达式不应用于给定的任务。做得好。 (2认同)

Rya*_*rle 25

Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);
Run Code Online (Sandbox Code Playgroud)

资源


zzz*_*Bov 17

@JasonTrue是正确的,剥离HTML标签不应该通过正则表达式完成.

使用HtmlAgilityPack剥离HTML标记非常简单:

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}
Run Code Online (Sandbox Code Playgroud)


Cou*_*ero 13

我想回应Jason的回应,虽然有时你需要天真地解析一些Html并提取文本内容.

我需要使用一些由富文本编辑器创建的Html,总是有趣和游戏.

在这种情况下,您可能需要删除某些标记的内容以及标记本身.

在我的情况下,标签被扔进这个混合.有些人可能会发现我(非常轻微)不太天真的实现是一个有用的起点.

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }
Run Code Online (Sandbox Code Playgroud)


Owi*_*dat 5

在此URL尝试正则表达式方法:http://www.dotnetperls.com/remove-html-tags

/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您有像这样的<div id ="x <4>">的HTML,它就不起作用 (2认同)