【问题标题】:What is the REGEX to match this pattern in a html document in C#?在 C# 的 html 文档中匹配此模式的正则表达式是什么?
【发布时间】:2009-05-27 11:21:30
【问题描述】:

我真的不知道如何最好地做到这一点,我可以做相当简单的正则表达式,但更复杂的表达式真的难倒我。

以下内容出现在特定的 HTML 文档中:

<span id="label">
<span>
<a href="http://variableLink">Joe Bloggs</a>
now using
</span>
<span>
'
<a href="/variableLink/">Important Data</a>
'
</span>
<span>
on
<a href="/variableLink">Important data 2</a>
</span>
</span>

我需要提取两个“重要数据”点,并且可能会花费数小时来计算正则表达式。(我在 C# 3.5 中使用 .net 正则表达式库)

【问题讨论】:

  • 恐怕我帮不了你,但如果你在 .NET RegEx 方面需要帮助,试试 Expresso ultrapico.com/Expresso.htm 它是免费的,非常适合测试 RegEx。
  • 必须使用正则表达式,还是可以使用 HTML 解析库,如 HTML Agility Pack (codeplex.com/htmlagilitypack)?
  • 我可以使用任何东西,不必是正则表达式。
  • 第一个和最后两个链接有什么区别?是否以 http:// 开头?
  • 您必须真正详细说明您的问题 - 从您对我的回答的评论中,我知道您只对特定 标记内的链接感兴趣。这产生了一个新问题 - 第一个链接周围的 标记与后面两个链接的 标记有何不同?身份属性?那么只有没有 id 属性的 span 内的链接?

标签: c# .net regex


【解决方案1】:

如前所述,正则表达式通常不是解析 HTML、XML 和朋友的正确工具 - 考虑使用 HTML 或 XML 解析库。如果你真的想或不得不使用正则表达式,下面的内容在很多情况下会匹配标签的内容,但在某些情况下可能仍然会失败。

<a href="[^"]*">(?<data>[^<]*)</a>

此表达式将匹配所有不以 http:// 开头的链接 - 这是我能看到的链接之间唯一明显的区别。

<a href="(?!http://)[^"]*">(?<data>[^<]*)</a>

【讨论】:

  • 这不也匹配 'Joe Bloggs' 和 html 文档中的任何其他链接吗?
  • 这也吸引了 Joe Bloggs。他说他只想要 2 个“重要”点。
  • 是的,我注意到了。我只是不知道他想如何区分这些链接。马修将不得不详细说明差异。
  • 第二个确实匹配链接,但它匹配 HTML 文档中的所有相似链接。我如何将其限制为该特定范围内的链接?
  • +1 指出正则表达式不是适合这项工作的工具。特别是。当 HTML 没有在语义上进行标记时。
【解决方案2】:

下面使用HtmlAgilityPack。它会在“标签”ID 内的第二个或以后的链接中打印任何文本。当然,修改 XPath 来做一些不同的事情是相对简单的。

    HtmlDocument doc = new HtmlDocument();
    doc.Load(new StringReader(@"<span id=""label"">
<span>
<a href=""http://variableLink"">Joe Bloggs</a>
now using
</span>
<span>
'
<a href=""/variableLink/"">Important Data</a>
'
</span>
<span>
on
<a href=""/variableLink"">Important data 2</a>
</span>
</span>
"));
    HtmlNode root = doc.DocumentNode;

    HtmlNodeCollection anchors;
    anchors = root.SelectNodes("//span[@id='label']/span[position()>=2]/a/text()");
    IList<string> importantStrings;
    if(anchors != null)
    {
        importantStrings = new List<string>(anchors.Count);
        foreach(HtmlNode anchor in anchors)
        importantStrings.Add(((HtmlTextNode)anchor).Text);
    }
    else
        importantStrings = new List<string>(0);

    foreach(string s in importantStrings)
        Console.WriteLine(s);

【讨论】:

  • 我知道他要求使用正则表达式,但我完全同意正则表达式会很糟糕。请注意,这并非不可能,但该死的几乎不可能维护,因为 html 和类似的正则表达式通常最终会出现大量的转义。特别是如果您希望超越单个标签。
【解决方案3】:

查找 .NET 的后视和前瞻语法,并使用它来查找 HTML 中的锚标记。 This site 可以帮助你。作为正则表达式的替代方法,您可以考虑使用 System.Xml.XPath.XPathNavigator 直接寻址这些节点。

【讨论】:

    【解决方案4】:

    我的正则表达式有点生疏,但以下内容可能会有所帮助(尽管它可能需要一些微调):

    (?<=\<a href="/variableLink[/]?"\>)(.*)+(?=</a>)
    

    【讨论】:

      【解决方案5】:
        <a\shref.*?"/variableLink/?">(.*)</a>
      

      第一组包含锚的名称。用 Expresso 测试。适用于您提供的示例文本。
      更新:也适用于 Snippy。

      Regex regex = new Regex(@"<a\shref.*?""/variableLink/?"">(.*)</a>", RegexOptions.Multiline);
      foreach (Match everyMatch in regex.Matches(sText))
      {
        Console.WriteLine("{0}", everyMatch.Groups[1]);
      }
      

      输出:

      Important Data
      Important data 2
      

      【讨论】:

        猜你喜欢
        • 2014-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-16
        • 1970-01-01
        • 1970-01-01
        • 2013-04-19
        • 1970-01-01
        相关资源
        最近更新 更多