HtmlAgilityPack从子节点中选择数据

时间:2015-05-09 17:59:22

标签: c# html linq parsing html-agility-pack

我有以下要解析的HTML代码:

<h3 class='bar'>
  <a href='http://anysite.com/index.php?showuser=7195' title='Profile view'>THIS_IS_USERNAME</a>
  &nbsp;
  <a href='http://anysite.com/index.php?showuser=7195&amp;f=' class='__user __id7195' title='Profile view'>
      <img src='http://anysite.com/public/style_images/car/user_popup.png' alt='' />
   </a>
</h3>

我需要的是选择用户名(“THIS_IS_USERNAME”)和个人资料的链接(“http://anysite.com/index.php?showuser=7195”)

我可以使用下一个代码选择顶级h3节点:

List<HtmlNode> resultSearch = HTMLPage.DocumentNode.Descendants()
                .Where(
                         x => x.Name.Equals("h3")
                         && x.Attributes["class"] != null
                         && x.Attributes["class"].Value.Equals("bar")                         
                      )
                .ToList();

但是我怎么能得不到“h3”节点本身,而是“a”里面的“h3”这个属性链接包含用户名和我需要的个人资料链接?

1 个答案:

答案 0 :(得分:1)

您可以直接查询链接节点,它与标题属性非常不同。

在这种情况下,使用XPath可能更简单,因为它处理所有中间空检查,并且它就像类型安全一样,因为你的Linq查询将有很多常量字符串:

var node = HTMLPage.DocumentNode.SelectSingleNode("//hr[@class='Bar']/a[@title='Profile View' and @href");
if (node != null)
{
    string link = node.Attributes["href"].Value;
    string username = node.InnerText;
}

您可以使用Linq语法编写类似的代码,它首先搜索链接标记,然后回溯以找到它的h3父级。这样你就不必检查中间空值;):

var node = HtmlPage.DocumentNode.Descendants("a")
    .Where(a =>
        a.Ascendants("h3")
            .Any(h3 =>
                h3.Attributes["class"] != null 
                && a.Attributes["class"].Value == "bar"
            )
    )
    .Where(a => 
        a.Attributes["title"] != null 
        && a.Attributes["title"].Value == "Profile View"
        && a.Attributes["href"] != null
    )
    .FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}

或者你可以使用它作为&#34; bar&#34;的第一个<a>孩子的位置:

// the call to First() will throw an exception if the h3 isn't found.
// returning an empty HtmlNode will allow you to ignore that

var node = (HtmlPage.DocumentNode.Descendants("h3")
    .FirstOrDefault( h => 
            h3.Attributes["class"] != null 
            && a.Attributes["class"].Value == "bar")
    ) ?? HtmlPage.CreateElement("h3")) 
    .Elements("a").FirstOrDefault();

if (node != null)
{
    string link = node.Attributes["href"].value;
    string username = node.InnerText;
}