使用HTML Agility Pack和Linq解析html

我有以下HTML

(..)    Test1   Data   Data 2     Test2   Data2   Data 2    (..) 

我的信息是name => so“Test1”和“Test2”。 我想知道的是如何根据我的名字获取“data”和“data2”中的数据。

目前我正在使用:

 var data = from tr in doc.DocumentNode.Descendants("tr") from td in tr.ChildNodes.Where(x => x.Attributes["class"].Value == "name") where td.InnerText == "Test1" select tr; 

但是当我尝试查看data时,我得到{"Object reference not set to an instance of an object."}

至于您的尝试,您的代码有两个问题:

  1. ChildNodes很奇怪 – 它还返回空白文本节点,它们没有class属性(当然不能有属性)。
  2. 正如詹姆斯沃尔福德评论的那样,文本周围的空间很重要,你可能想要修剪它们。

通过这两个更正,以下工作:

 var data = from tr in doc.DocumentNode.Descendants("tr") from td in tr.Descendants("td").Where(x => x.Attributes["class"].Value == "name") where td.InnerText.Trim() == "Test1" select tr; 

这是XPATH方式 – 嗯……每个人似乎都忘记了XPATH的强大function,专注于C#XLinq,这些天:-)

此函数获取与名称关联的所有数据值:

 public static IEnumerable GetData(HtmlDocument document, string name) { return from HtmlNode node in document.DocumentNode.SelectNodes("//td[@class='name' and contains(text(), '" + name + "')]/following-sibling::td") select node.InnerText.Trim(); } 

例如,此代码将转储所有“Test2”数据:

  HtmlDocument doc = new HtmlDocument(); doc.Load(yourHtml); foreach (string data in GetData(doc, "Test2")) { Console.WriteLine(data); } 

这是一种方法 – 首先将所有数据解析为数据结构,然后读取它。 这有点乱,肯定需要更多validation,但是这里有:

 HtmlWeb hw = new HtmlWeb(); HtmlDocument doc = hw.Load("http://jsbin.com/ezuge4"); HtmlNodeCollection nodes = doc.DocumentNode .SelectNodes("//table[@id='MyTable']//tr"); var data = nodes.Select( node => node.Descendants("td") .ToDictionary(descendant => descendant.Attributes["class"].Value, descendant => descendant.InnerText.Trim()) ).ToDictionary(dict => dict["name"]); string test1Data = data["Test1"]["data"]; 

在这里,我将每个

转换为字典,其中

的类是键,文本是值。 接下来,我将字典列表转换为字典字典(tip – abstract away),其中每个

name都是关键字。

代替

 td.InnerText == "Test1" 

尝试

 td.InnerText == " Test1 " 

要么

 d.InnerText.Trim() == "Test1" 

我可以推荐以下两种方式之一:

http://htmlagilitypack.codeplex.com/ ,它将html转换为有效的xml,然后可以使用OOTB Linq查询。

要么,

Linq to HTML( http://www.superstarcoders.com/linq-to-html.aspx )虽然没有在CodePlex上保留(这是一个提示,Keith),但它提供了一套合理的工作function组合。