【问题标题】:Using C# regular expressions to remove HTML tags使用 C# 正则表达式删除 HTML 标签
【发布时间】:2010-10-21 17:41:01
【问题描述】:

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

【问题讨论】:

  • 您没有指出,但我推断您还想完全删除脚本和样式元素,而不仅仅是删除标签。下面的 HTML Agility Pack 答案对于删除标签是正确的,但要删除脚本和样式,您还需要类似 stackoverflow.com/questions/13441470/… 的内容
  • 表示为重复的问题有很多信息(还有小马托尼!),但它只要求打开标签,而不是所有标签。所以我不确定它在技术上是重复的。也就是说,答案是一样的:不要。

标签: c# html regex parsing


【解决方案1】:
Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);

Source

【讨论】:

    【解决方案2】:

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

    您可以使用以下内容。

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

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

    【讨论】:

    • 这是一个幼稚的实现。也就是说,不幸的是,
      是有效的 html。虽然处理大多数理智的情况..
    • 如前所述,我知道这个表达式在某些情况下会失败。我什至不确定是否可以通过任何正则表达式处理一般情况而不会出错。
    • 不,这在所有情况下都会失败!它的贪婪。
    • @Cipher,你为什么认为贪婪是个问题?假设匹配从有效 HTML 标记的开头开始,它永远不会超出该标记的结尾。这就是 [^>] 的用途。
    • @AlanMoore html 不是“常规语言”,即您无法正确匹配所有有效的 html 与正则表达式。见:stackoverflow.com/questions/590747/…
    【解决方案3】:

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

    编辑添加:

    为了厚颜无耻地从 jesse 下面的评论中窃取信息,并且为了避免被指责在这么长时间之后没有充分回答问题,这里有一个简单、可靠的 sn-p,它使用了 HTML 敏捷包,即使是最不完美的、反复无常的一些 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());
    

    使用正则表达式解析 HTML 的辩护案例非常少,因为如果没有上下文感知,即使在非传统的正则表达式引擎中也很难提供上下文感知,因此 HTML 无法正确解析。您可以通过 RegEx 部分实现,但您需要进行手动验证。

    Html Agility Pack 可以为您提供强大的解决方案,减少手动修复因将 HTML 视为上下文无关语法而导致的异常的需要。

    一个正则表达式可能会在大多数情况下为您提供大部分您想要的东西,但在非常常见的情况下它会失败。如果你能找到比 HTML Agility Pack 更好/更快的解析器,那就去吧,但请不要让世界遭受更多破碎的 HTML 黑客攻击。

    【讨论】:

    • HTML Agility Pack 并不能解决与使用 HTML 相关的所有问题(例如,如果您只想使用 HTML 代码片段怎么办?!)。
    • 它与 HTML 片段配合得非常好,它是原始海报描述的场景的最佳选择。另一方面,正则表达式仅适用于理想化的 HTML,并且会破坏完全有效的 HTML,因为 HTML 的语法不规则。如果他使用 Ruby,我仍然会建议使用 nokogiri 或 hpricot,或用于 Python 的 beautifulsoup。最好将 HTML 视为 HTML,而不是一些没有语法的任意文本流。
    • HTML 不是正则语法,因此不能单独使用正则表达式进行解析。您可以使用正则表达式进行词法分析,但不能用于解析。真的就是这么简单。甚至在 HTML 出现之前,语言学家就已经同意这一点。
    • 这不是意见问题。大多数时候,正则表达式可能会得到你想要的东西,但在非常常见的情况下它会失败。如果你能找到比 HTML Agility Pack 更好/更快的解析器,那就去吧,但请不要让世界遭受更多破碎的 HTML 黑客攻击。
    • 如果不解析 HTML,您将无法可靠地正确识别 HTML 标签。您了解 HTML 的所有语法吗?请参阅其他答案所建议的“非常接近”的邪恶黑客,并告诉我您为什么要保持这一点。对我投反对票是因为对您的示例输入有效的快速尝试不会使您的解决方案正确。我偶尔会使用正则表达式从 HTML 内容生成报告,或者使用 > 上的否定匹配来修复一些 CSS 引用。限制出错的机会,但我们做了额外的验证;这不是通用的。
    【解决方案4】:

    这个问题太宽泛,无法明确回答。您是在谈论从真实世界的 HTML 文档(如网页)中删除所有标签吗?如果是这样,您必须:

    • 删除 ?xml prolog(如果存在)
    • 删除所有 SGML cmets
    • 删除整个 HEAD 元素
    • 删除所有 SCRIPT 和 STYLE 元素
    • 用 FORM 和 TABLE 元素做 Grabthar-knows-what
    • 删除剩余的标签
    • 从 CDATA 部分中删除 序列,但保留其内容

    这只是我的想法——我相信还有更多。一旦你完成了所有这些,你最终会在某些地方出现单词、句子和段落,而在其他地方则出现大量无用的空白。

    但是,假设您只使用一个片段并且您可以简单地删除所有标签,这是我将使用的正则表达式:

    @"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"
    

    在各自的备选方案中匹配单引号和双引号字符串足以处理属性值中的尖括号问题。我认为没有必要明确匹配标签内的属性名称和其他内容,就像 Ryan 回答中的正则表达式一样;第一个替代方案处理所有这些。

    如果您想知道(?&gt;...) 构造,它们是atomic groups。它们使正则表达式更有效率,但更重要的是,它们可以防止失控的回溯,当你像我所做的那样混合交替和嵌套量词时,你应该始终注意这一点。我真的不认为这会是一个问题,但我知道如果我不提及它,其他人会。 ;-)

    当然,这个正则表达式并不完美,但它可能与您所需要的一样好。

    【讨论】:

    • 这是迄今为止最好的答案。您回答了发帖人的问题并解释了为什么不应该将正则表达式用于给定任务。干得好。
    【解决方案5】:

    使用这个..

    @"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"
    

    【讨论】:

      【解决方案6】:

      我想回应 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"
          }
      

      【讨论】:

      • 除了明显的跨平台换行问题外,在内容分隔时使用不贪婪的量词会很慢。使用&lt;xml&gt;.*(?!&lt;/xml&gt;)&lt;/xml&gt; 之类的东西,前两个使用RegexOptions.SingleLine 修饰符,最后一个使用&lt;[^&gt;]*&gt;。第一个也可以通过在第一个标签名称中捕获的交替以及在负前瞻和最终标签中对其进行反向引用来组合。
      【解决方案7】:

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

      使用 HtmlAgilityPack 去除 HTML 标签非常简单:

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

      【讨论】:

      • 虽然我对此有点晚了,但我想提一下,这也适用于 Word 和其他办公产品生成的 xml。任何需要处理 Word xml 的人都会很好地考虑使用它,因为它确实有很大帮助,特别是如果您需要从内容中删除标签,而这正是我需要的。
      • 当一切似乎都失败了,这个简单的代码 sn-p 拯救了这一天。谢谢!
      • 任何人都遇到了“路径中的非法字符”异常。当调试运行到行 doc.LoadHtml?
      【解决方案8】:

      在此 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);
      }
      

      【讨论】:

        【解决方案9】:

        &lt;[^&gt;]*&gt; 中添加.+? 并尝试这个正则表达式(基于this):

        <[^>].+?>
        

        c# .net regex demo

        【讨论】:

          【解决方案10】:

          使用此方法去除标签:

          public string From_To(string text, string from, string to)
          {
              if (text == null)
                  return null;
              string pattern = @"" + from + ".*?" + to;
              Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
              MatchCollection matches = rx.Matches(text);
              return matches.Count <= 0 ? text : matches.Cast<Match>().Where(match => !string.IsNullOrEmpty(match.Value)).Aggregate(text, (current, match) => current.Replace(match.Value, ""));
          }
          

          【讨论】:

            猜你喜欢
            相关资源
            最近更新 更多
            热门标签