HtmlAgility Pack获取单个节点获取null值

时间:2016-02-29 01:13:09

标签: xpath html-agility-pack

我正在尝试使用XPath获取单个节点,但我在节点上获得空值,并且知道为什么

        WebClient wc = new WebClient();
        string nodeValue;
        string htmlCode = wc.DownloadString("http://www.freeproxylists.net/fr/?c=&pt=&pr=&a%5B%5D=0&a%5B%5D=1&a%5B%5D=2&u=50");
        HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
        html.LoadHtml(htmlCode);
        HtmlNode node = html.DocumentNode.SelectSingleNode("//table[@class='DataGrid']/tbody/tr[@class='Odd']/td/a");
        nodeValue = (node.InnerHtml);

1 个答案:

答案 0 :(得分:0)

我发现你的xpath中至少有2个错误,而你试图从中获取信息。

  1. 没有< a>有< tr class = Odd“>作为祖先。
  2. 即使你的Xpath有效,你也只能得到一个< td>因为你决定使用SelectSingleNode而不是SelectNodes
  3. 看起来它正在对你正在尝试做的事情做一些懒惰的保护。由于a-tag只是用IPDecode中的十六进制表示。所以提取链接真的没问题。但至少你可以做的是在发布之前查看html。你显然没有尝试过。由于您从当前代码获取的html不是< body>你给我们的链接 - 意味着你必须从绝对网址获取htmlpage或只是使用Selenium。

    但是,由于我是一个如此膨胀的家伙,我将使用 Xpath,Html Agility Pack和Selenium 为您制作完整的解决方案。以下解决方案获取该网站的HTML。然后只读取< tr>有class =“奇数”。之后,它找到所有“加密的”< a>。并将它们解码为一个字符串并将它们写入一个数组。之后,有一个如何从一个锚点获取属性值的小例子。

        private void HtmlParser(string url)
        {
            HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
            htmlDoc.OptionFixNestedTags=true;
    
            GetHTML(url);
            htmlDoc.Load("x.html", Encoding.ASCII, true);      
    
            HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//table[@class='DataGrid']/descendant::*/tr[@class='Odd']/td/script");
            List<string> urls = new List<string>();
    
            foreach(HtmlNode x in nodes)
            {
                urls.Add(ConvertStringToUrl(x.InnerText));
            }
    
            Console.WriteLine(ReadingTheAnchor(urls[0]));
        }
    
        private string ConvertStringToUrl(string octUrl)
        {
    
            octUrl = octUrl.Replace("IPDecode(\"", "");
            octUrl = octUrl.Remove(octUrl.Length -2);
            octUrl = octUrl.Replace("%", "");
            string ascii = string.Empty;
    
            for (int i = 0; i < octUrl.Length; i += 2)
            {
                String hs = string.Empty;
    
                hs   = octUrl.Substring(i,2);
                uint decval =   System.Convert.ToUInt32(hs, 16);
                char character = System.Convert.ToChar(decval);
                ascii += character;
    
            }
            //Now you get the <a> containing the links. which all can be read as seperate html files containing just a <a>
            Console.WriteLine(ascii);
            return ascii;
        }
    
        private string ReadingTheAnchor(string anchor)
        {
            //returns url of anchor
            HtmlDocument anchorHtml = new HtmlAgilityPack.HtmlDocument();
            anchorHtml.LoadHtml(anchor);
            HtmlNode h = anchorHtml.DocumentNode.SelectSingleNode("a");
            return h.GetAttributeValue("href", "");
        }
    
        //using OpenQA.Selenium; using OpenQA.Selenium.Firefox;
        private void GetHTML(string url)
        {
            using (var driver = new FirefoxDriver())
            {
                driver.Navigate().GoToUrl(url);
                Console.Clear();
                System.IO.File.WriteAllText("x.html", driver.PageSource);
            }
        }