首页 > 解决方案 > HtmlAgilityPack 的可见区域有多深?

问题描述

我需要从博客中获取一些帖子。一切顺利,直到我想获得帖子创建日期。它的 DOM 树是:

div class="stories-feed__container" 
  -> article 
     -> div class="story__main" 
       -> div class="story__footer" 
         -> div class="story__user user" 
           -> div class="user__info-item" 
             -> time datetime="date and time in UTC format".

所以我写了代码:

    HtmlWeb web = new HtmlWeb();
    HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
    doc = web.Load("https://pikabu.ru/@serhiy1994");
    string postDate = doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'stories-feed__container')]/article[2]/div[contains(@class, 'story__main')]/div[contains(@class, 'story__footer')]/div[contains(@class, 'story__user user')]/div[contains(@class, 'user__info-item')]/time").GetAttributeValue("datetime", "NULL"); // e.g. for the 2nd article on the page

它返回NullReferenceException. 但是如果你停在“div class="story__user"”级别(例如,

    string postDate = doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'stories-feed__container')]/article[2]/div[contains(@class, 'story__main')]/div[contains(@class, 'story__footer')]/div[contains(@class, 'story__user user')]").InnerHtml;

它可以正常工作并返回内部 HTML 代码。所以我认为 HtmlAgilityPack 有类似“最大可见性级别”的东西,你将无法使用更深的降价进行操作。

我是对的还是我编码错了?

原始页面代码在这里:https ://pastebin.com/jFC0XD9C

标签: c#html-agility-pack

解决方案


HtmlAgility 将抓取整个网站,无论您想去多深。您可以使用它来找到您正在寻找的项目,因为您不必提供整个路径。

这将搜索整个站点并查找<div>具有类名的第一个标签user__info-item。如果有多个标签,您还可以更改SelectSingleNodeSelectNodes,然后遍历它们以获取日期。

    HtmlWeb web = new HtmlWeb();
    HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
    doc = web.Load("https://pikabu.ru/@serhiy1994");
    var postDate = doc.DocumentNode.SelectSingleNode("//div[@class='user__info-item']/time");
    Console.WriteLine(postDate.InnerText);

你的代码有什么问题?

您上面的代码不起作用的原因是因为您缺少另一个 div ' <div class="user__info user__info_left">'。

如果你这样写你的代码,它就可以工作。

    var nodes = doc.DocumentNode.SelectSingleNode("//div[@class='story__main']/div[@class='story__footer']/div[@class='story__user user']/div[@class='user__info user__info_left']/div[@class='user__info-item']/time");
    Console.WriteLine(nodes.InnerText);

另一种方式

另一种方法是搜索父 div。找到父标签后,在该标签下搜索以找到您要查找的内容。

    var nodes = doc.DocumentNode.SelectNodes("//div[@class='story__user user']");
    foreach (HtmlNode node in nodes)
    {
        // Search within each node using .// notation
        var timeNodes = node.SelectSingleNode(".//div[@class='user__info-item']/time");
        Console.WriteLine(timeNodes.InnerText);
    }

测试代码在这里


推荐阅读