繁体   English   中英

正则表达式遇到麻烦

[英]Having trouble with regular expression

我是一个总的菜鸟在正则表达式,需要解析一些HTML。 我正在寻找个别类别。 以下是html的外观:

<p>Categories: 
        <a href="/some/URL/That/I/dont/need">Category1</a>  | 
        <a href="/could/be/another/URL/That/I/dont/need">Category2</a> 
</p> 

可能有1-5个类别。 我需要的是“ Category1或Category2等”

该项目是使用Visual Studio 2010的C#。目前,我拥有的是:

private static readonly Regex _categoriesRegex = new Regex("(<p>Categories:)((/w/.?<Categories>.*?).*?)(</p>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);

我知道我可能还很遥远,但想知道是否有人至少可以带领我朝正确的方向发展。

不要将正则表达式用于此类任务,而应使用专用工具。 最好的选择可能是使用HTML Agility Pack


编辑:这是使用HTML Agility Pack(以LINQPad编写)的示例:

void Main()
{
    var doc = new HtmlDocument();
    doc.Load(@"D:\tmp\foobar.html");
    var query =
        from p in doc.DocumentNode.Descendants("p")
        where p.InnerText.StartsWith("Categories:")
        from a in p.Elements("a")
        select a.InnerText;

    query.Dump();
}

它返回:

Category1
Category2

我应该注意,这是我第一次真正尝试使用HAP,并且它是如此的容易让我感到惊讶(上面的代码编写大约花了3分钟)。 该API与Linq to XML非常相似,如果您对Linq感到满意的话,则使其非常直观。

通常针对这些类型的问题建议使用HTML Agility Pack(HAP), Thomas的解决方案很棒,但是, 如果您可以保证输入格式正确并且期望的结果简单明了,通常我不是100% 。 如果是这种情况,那么通常可以使用LINQ to XML而不是将HAP引入项目。 我在下面演示这种方法。 鉴于非嵌套输入易于处理,因此我还加入了正则表达式方法,因为您的请求不太繁琐。

我建议您坚持使用LINQ解决方案,因为它易于维护并且易于他人理解。 添加正则表达式只是为了演示如何做到这一点并解决您的原始问题。

string input = @"<p>Categories: 
        <a href=""/some/URL/That/I/dont/need"">Category1</a>  | 
        <a href=""/could/be/another/URL/That/I/dont/need"">Category2</a> 
</p>";

// LINQ to XML approach for well formed HTML
var xml = XElement.Parse(input);
var query = xml.Elements("a").Select(e => e.Value);
foreach (var item in query)
{
    Console.WriteLine(item);
}

// regex solution
string pattern = @"Categories:(?:[^<]+<a[^>]+>([^<]+)</a>)+";

Match m = Regex.Match(input, pattern);
if (m.Success)
{
    foreach (Capture c in m.Groups[1].Captures)
    {
        Console.WriteLine(c.Value);    
    }
}

在@Thomas Levesque答案中添加一点(这是正确的方法):

如果要获取链接而不是<a>标记之间的文本,则只需执行以下操作:

    var query =
        from p in doc.DocumentNode.Descendants("p")
        where p.InnerText.StartsWith("Categories:")
        from a in p.Elements("a")
        select a.Attributes["href"].Value;

编辑 :如果您不熟悉LINQ语法,则可以通过以下方法获得相同的结果:

var nodes = doc.DocumentNode.SelectNodes("//p"); //Here I get all the <p> tags in the document
if (nodes != null)
{
    foreach (var n in nodes)
    {
        if (n.InnerText.StartsWith("Categories:")) //If the <p> tag we need was found
        {
            foreach (var a in n.SelectNodes("./a[@href]")) //Iterating through all <a> tags that are next to the <p> tag (childs)
            {
                //It will print something like: "Name: Category1        Link: /some/URL/That/I/dont/need
                Console.WriteLine("Name: {0} \t Link: {1}", a.InnerText, a.Attributes["href"].Value; 
            }
            break;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM