【问题标题】:Unable to get html element by using X-Path in HtmlAgilityPack C#无法在 HtmlAgilityPack C# 中使用 X-Path 获取 html 元素
【发布时间】:2019-08-10 04:52:02
【问题描述】:

我正在尝试通过使用 x-path 树元素但显示为 null 来获取元素,并且这种类型的 x-path 对我来说适用于其他站点,只有 2% 的站点这种类型的 X-Path 不起作用,我也尝试过来自 chrome 的 x-path 也是,但是当我的 x-path 不起作用时,chrome x-path 也不起作用。

public static void Main()
    {
        string url = "http://www.ndrf.gov.in/tender";
        HtmlWeb web = new HtmlWeb();
        var htmlDoc = web.Load(url);
        var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/div[2]/table[1]"); // i want this type // not wroking
        //var nodetest2 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]/div/div[1]/div[2]/table"); // from Google chrome // not wroking
        //var nodetest3 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]"); // by ID but i don't want this type  // wroking
        Console.WriteLine(nodetest1.InnerText); //fail
        //Console.WriteLine(nodetest2.InnerText); //fail
        //Console.WriteLine(nodetest3.InnerText); //proper but I don't want this type
    }

【问题讨论】:

  • 不清楚你在追求什么。您打算写出整张表还是一行?还是别的什么?
  • 我还建议使用anglesharp 代替敏捷包。敏捷包似乎不再维护了。
  • QHarr 感谢您的回复...我想要整张桌子

标签: c# .net html-agility-pack


【解决方案1】:

@QHarr 建议的答案完美无缺,但是使用正确的 x 路径获得 null 的原因是有 a javascript file in the header of the site,它在桌子周围添加了一个包装器 div,并且因为在 HtmlAgilityPack 中获得了结果好像没有加载或执行js,x-path返回null。

你观察到,在 js 运行之后是:

<div class="view-content">
      <div class="guide-text">
          ...
      </div>
      <div class="scroll-table1">
          <!-- Your table is here -->
      </div>
</div>

但是没有那个 js,实际上你得到的是:

<div class="view-content">
    <!-- Your table is here -->
</div>

因此您的 x-path 应该是:

var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/table[1]");

【讨论】:

  • Ali Bordbar 感谢您的回答。您的 X-Path 树完美运行。但是在我的项目中,当时会有多个站点我如何确定是否有任何包装器 div。因为我正在生成完美的 HTML X-Path 树。
  • 好吧,确保此类事情不会发生的一种方法是在没有 javascript 的情况下浏览您的目标网页。禁用 javascript,在 this answer 中解释并刷新您的页面,然后使用 x-path 找到正确的元素
【解决方案2】:

在浏览器中使用时,您的 xpath 会选择整个表格。可以按如下方式缩短使用(fiddle):

using System;
using HtmlAgilityPack;

public class Program
{

    public static void Main()
    {
        string url = "http://www.ndrf.gov.in/tender";
        HtmlWeb web = new HtmlWeb();
        var htmlDoc = web.Load(url);
        var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("//table");  
        Console.WriteLine(nodetest1.InnerText); 
    }
}

【讨论】:

  • QHarr 感谢您的回复..如果有多个表格而不是您应该做什么..重要的想法是在我的项目中,当他选择元素时,我让用户在鼠标悬停在 WebBrowser 控件上时选择元素那时我的代码会生成 X-Path。
  • 当用户在 WebBrowser 控件中加载网站时,当他通过鼠标单击选择时,该网站具有任何标签,如 table、div span 等,因此没有修复 //table 元素或任何其他元素。
  • 没有什么神奇的方法,当然也不用xpath。例如,有一些方法可以动态遍历直到找到某个值。如果多个表然后选择多个节点和循环是一种方式。听起来你期待的答案将与在浏览器中右键单击复制 xpath 相同,这超出了本网站的范围。
【解决方案3】:

使用 Fizzler.Systems.HtmlAgilityPack 详情在这里:https://www.nuget.org/packages/Fizzler.Systems.HtmlAgilityPack/ 该库添加了名为 QuerySelector 和 QuerySelectorAll 的扩展方法,它们采用 CSS Selector 而不是 XPath。

【讨论】:

    【解决方案4】:

    Ali Bordbar 完美,当我在加载所有 JavaScript 文件的 WebBrowser 控件中导航 URL 时,此 Url 添加了一个包装 div, 但是当我使用 HtmlWeb 加载 URL 时,没有加载任何 JavaScript 文件。 HtmlWeb 检索服务器发送的静态 HTML 响应,并且不执行任何 javascript,而 WebBrowser 会。 所以 WebBrowser 控制 HTML DOM 数据 XPath 和 HtmlWeb HTML DOM 数据 XPath 不匹配。

    我下面的代码非常适合这个切换

    HtmlWeb web = new HtmlWeb();
    web.AutoDetectEncoding = true;
    HtmlAgilityPack.HtmlDocument theDoc1 = web.Load("http://www.ndrf.gov.in/tender");
    var HtmlDoc = new HtmlAgilityPack.HtmlDocument();
    var bodytag = theDoc1.DocumentNode.SelectSingleNode("//html");
    HtmlDoc.LoadHtml(bodytag.OuterHtml);
    var xpathHtmldata = HtmlDoc.DocumentNode.SelectSingleNode(savexpath); //savexpath is my first xpath make from HTML DOM data of WebBrowser control which is work for most url.
    if (xpathHtmldata == null)
    {
        //take last tag name from first xpath
        string mainele = savexpath.Substring(savexpath.LastIndexOf("/") + 1);
        if (mainele.Contains("[")) { mainele = mainele.Remove(mainele.IndexOf("[")); }
        //collect all tag name with name of which is sotre in mainele variable
        var taglist = HtmlDoc.DocumentNode.SelectNodes("//" + mainele);
        foreach (var ele in taglist) //check one by one element 
        {
            string htmltext1 = ele.InnerText;
            htmltext1 = Regex.Replace(htmltext1, @"\s", "");
            htmltext1 = htmltext1.Replace("&amp;", "&").Trim();
            htmltext1 = htmltext1.Replace("&nbsp;", "").Trim();
    
            string htmltext2 = saveInnerText; // my previus xpath text from HTML DOM data of WebBrowser control
            htmltext2 = Regex.Replace(htmltext2, @"\s", "");
    
            if (htmltext1 == htmltext2) // check equality to my previus xpath text..if it is equal thats my new xpath
            {
                savexpath = ele.XPath;
                break;
            }
        }
    } 
    

    【讨论】:

      猜你喜欢
      • 2011-05-20
      • 1970-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      相关资源
      最近更新 更多