我是正则表达式的总菜鸟,需要解析一些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);
我知道我可能会离开,但想知道是否有人能够至少引导我朝着正确的方向前进。
答案 0 :(得分:6)
请勿使用正则表达式执行此类任务,请改用专用工具。您最好的选择可能是使用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感到满意,这将非常直观。
答案 1 :(得分:1)
通常会针对这些类型的问题建议使用HTML Agility Pack(HAP),Thomas' solution很棒,但我通常不是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);
}
}
答案 2 :(得分:0)
Addint一点点@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;
}
}
}