使用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."}
至于您的尝试,您的代码有两个问题:
-
ChildNodes
很奇怪 – 它还返回空白文本节点,它们没有class
属性(当然不能有属性)。 - 正如詹姆斯沃尔福德评论的那样,文本周围的空间很重要,你可能想要修剪它们。
通过这两个更正,以下工作:
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组合。