【问题标题】:use RegEx to extract text between html tags使用 RegEx 提取 html 标签之间的文本
【发布时间】:2010-09-13 17:26:05
【问题描述】:

我必须从 Visual Basic 中的字符串中提取一些文本,如下所示:

<div id="div">
<h2 id="id-date">09.09.2010</h2> , here to extract the date 

<h3 id="nr">000</h3> , here a number </div>

我需要从 div 中提取日期,并从 div 中提取所有这些数字... 此外,这将处于循环中,这意味着需要解析更多的 div 块。! 谢谢你! 阿德里安

【问题讨论】:

  • HTML 是 not regular,因此不应使用正则表达式进行解析。使用 DOM 解析器。

标签: .net regex visual-studio


【解决方案1】:

使用正则表达式解析 HTML 并不理想。其他人建议使用 HTML Agility Pack。但是,如果您可以保证您的输入是明确定义的并且您始终知道会发生什么,那么使用正则表达式是可能的。

如果您能做出这样的保证,请继续阅读。否则,您需要考虑其他建议或更好地定义您的输入。事实上,你应该更好地定义你的输入,因为我的回答做了一些假设。需要考虑的一些问题:

  • HTML 是一行还是多行,由换行符分隔?
  • HTML 是否总是采用&lt;div&gt;...&lt;h2...&gt;...&lt;/h2&gt;&lt;h3...&gt;...&lt;/h3&gt;&lt;/div&gt; 的形式?或者可以有h1-h6标签吗?
  • hN 标记之上,日期和数字是否始终位于id 属性具有id-datenr 值的标记之间?

根据这些问题的答案,模式可能会发生变化。下面的代码假定每个 HTML 片段都遵循您共享的结构,它将有一个 h2h3 分别带有日期和数字,并且每个标签都将在一个新行上。如果你给它提供不同的输入,它可能会中断,直到模式与你的输入结构匹配。

Dim input As String = "<div id=""div"">" & Environment.Newline & _
               "<h2 id=""id-date"">09.09.2010</h2>" & Environment.Newline & _
               "<h3 id=""nr"">000</h3>" & Environment.Newline & _
               "</div>"

Dim pattern As String = "<div[^>]+>.*?" & _
                 "<h2\sid=""id-date"">(?<Date>\d{2}\.\d{2}\.\d{4})</h2>.*?" & _
                 "<h3\sid=""nr"">(?<Number>\d+)</h3>.*?</div>"

Dim m As Match = Regex.Match(input, pattern, RegexOptions.Singleline)

If m.Success Then
    Dim actualDate As DateTime = DateTime.Parse(m.Groups("Date").Value)
    Dim actualNumber As Integer = Int32.Parse(m.Groups("Number").Value)
    Console.WriteLine("Parsed Date: " & m.Groups("Date").Value)
    Console.WriteLine("Actual Date: " & actualDate)
    Console.WriteLine("Parsed Number: " & m.Groups("Number").Value)
    Console.WriteLine("Actual Number: " & actualNumber)
Else
    Console.WriteLine("No match!")
End If

图案可以在一条线上,但为了清楚起见,我将其分开。 RegexOptions.Singleline 用于允许 . 元字符处理 \n 换行符。

你也说过:

而且这将是循环的,意思是 需要更多的 div 块 已解析。

您是否在单独的字符串上循环?或者您是否期望在单个字符串中多次出现上述 HTML 结构?如果是前者,则应将上述代码应用于每个字符串。对于后者,您需要使用 Regex.Matches 并将每个 Match 结果与上述代码类似。


编辑:这里是一些示例代码,用于演示解析多个匹配项。

Dim input As String = "<div id=""div"">" & Environment.Newline & _
               "<h2 id=""id-date"">09.09.2010</h2>" & Environment.Newline & _
               "<h3 id=""nr"">000</h3>" & Environment.Newline & _
               "</div>" & _
               "<div id=""div"">" & Environment.Newline & _
               "<h2 id=""id-date"">09.14.2010</h2>" & Environment.Newline & _
               "<h3 id=""nr"">123</h3>" & Environment.Newline & _
               "</div>"

Dim pattern As String = "<div[^>]+>.*?" & _
                 "<h2\sid=""id-date"">(?<Date>\d{2}\.\d{2}\.\d{4})</h2>.*?" & _
                 "<h3\sid=""nr"">(?<Number>\d+)</h3>.*?</div>"

For Each m As Match In Regex.Matches(input, pattern, RegexOptions.Singleline)
    Dim actualDate As DateTime = DateTime.Parse(m.Groups("Date").Value)
    Dim actualNumber As Integer = Int32.Parse(m.Groups("Number").Value)
    Console.WriteLine("Parsed Date: " & m.Groups("Date").Value)
    Console.WriteLine("Actual Date: " & actualDate)
    Console.WriteLine("Parsed Number: " & m.Groups("Number").Value)
    Console.WriteLine("Actual Number: " & actualNumber)
Next

【讨论】:

  • 是的,将在单独的行上,是的,它将仅包含 div,h2,h3 ...是的将与格式化完全相同...。是的,这是一个大字符串,包含多个相似信息块....
  • @Adrian:我已经更新了我的答案,以展示如何使用Regex.Matches 方法和For Each 循环来处理多次出现。
【解决方案2】:

您不应该使用正则表达式解析 HTML,因为正如 Daniel Vandersluis 所说,HTML 不是正则的。您可以使用HTML Agility Pack

【讨论】:

【解决方案3】:

为什么不直接使用 Html Agility Pack ?

【讨论】:

    【解决方案4】:

    如果你的HTML tagattributes,那么这是我的解决方案:

    <TAG(.*?)>(.*?)</TAG>
    

    示例(使用 C#):

    var regex = new System.Text.RegularExpressions.Regex("<h1(.*?)>(.*?)</h1>");
    var m = regex.Match("Hello <h1 style='color: red;'>World</h1> !!");
    Console.Write(m.Groups[2].Value); // will print -> World
    

    【讨论】:

      【解决方案5】:

      试试这个来自link -

      private string StripHTML(string htmlString)
      {
          //This pattern Matches everything found inside html tags;
          //(.|\n) - > Look for any character or a new line
          // *?  -> 0 or more occurences, and make a non-greedy search meaning
          //That the match will stop at the first available '>' it sees, and not at the last one
          //(if it stopped at the last one we could have overlooked 
          //nested HTML tags inside a bigger HTML tag..)
          // Thanks to Oisin and Hugh Brown for helping on this one...
      
          string pattern = @"<(.|\n)*?>";  
      
          return  Regex.Replace(htmlString,pattern,string.Empty);
      }
      

      【讨论】:

      • “html标签内”与“html标签之间”不一样
      • @adf88 - 这是一个函数,您可以将 HTML 字符串传递给该函数,它会在删除 html 标记后返回值。所以这取决于用户传递给这个函数的内容。在这种情况下,用户需要传递 '

        000

        ' 作为输入,它将返回 000 作为输出。为什么这是错误的?
      • 如果我在
        里面有那些标签...
      • @Adrian - 我同意这不是一种完整的 html 解析方法,但对于给定的问题,它适合并获得用户所需的答案。对吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多