【问题标题】:get all td in XPath c#在 XPath c# 中获取所有 td
【发布时间】:2018-01-01 01:52:10
【问题描述】:

我正在尝试在 C# 中使用 HtmlAgilityPack 解析 HTML。我有21 tr items,每个 tr 项目都有7 td items。如何按顺序获取所有 tr 和 td 项目?现在我只能得到一个 tr 项目和它的 7 个 td 项目。

这是我的 C# 代码:

var url = "url";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream());
            string sourceCode = sr.ReadToEnd();

            HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
            document.LoadHtml(sourceCode);


            var name = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[2]/a[1]")[0].InnerText;
            var year = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[3]")[0].InnerText;
            var km = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[4]")[0].InnerText;
            var color = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[5]")[0].InnerText;
           var price = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[6]")[0].InnerText;
            var date = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[7]")[0].InnerText;
            var location = document.DocumentNode.SelectNodes("//*[@id=\"searchResultsTable\"]/tbody/tr[1]/td[8]")[0].InnerText;

我尝试使用[@id=\"searchResultsTable\"]/tbody/tr[1]/td[position()<8],但只返回 /n

【问题讨论】:

    标签: c# html xpath html-agility-pack


    【解决方案1】:

    试试下面的代码(未经测试。编译错误的机会。但给你一个想法。)

    代码中的注释为您提供更多详细信息。

    //GET THE TABLE NODE
    HtmlNode table = document.DocumentNode.SelectSingleNode("//*[@id='searchResultsTable']");
    
    //LOOP THROUGH THE TABLE NODE AND FIND EACH TR 
    foreach (HtmlNode row in table.SelectNodes("//tr")) {
    
          //PRINT HERE WHATEVER YOU WANT FOR EACH ROW.
          Console.WriteLine("New Row");
    
          //LOOP THROUGH THE ALL TD OF EACH TR
          foreach (HtmlNode cell in row.SelectNodes("//td")) {
              //PRINT HERE EACH TD
              Console.WriteLine("cell: " + cell.InnerText);
          } //END TD
    
    }//END TR
    

    【讨论】:

    • 我已经测试了你的代码。不是“td”和“tr”,而是“//td”和“//tr”。否则它会卡在 tbody 中并且找不到它们。有了这个改变,它就可以正常工作了。
    • 谢谢!该解决方案工作正常!有什么办法可以不让 div 在 tr/td. //*[@id="searchResultsTable"]/tbody/tr[1]/td[2]/div[1]/div[1]/a[1]我不想得到这些 div。我只想得到tds。 @katamarayudu @derloopkat
    • @heyaa cell.ChildNodes.First().InnerText 将获取 td 根级别的文本并忽略嵌套标签的内容。例如 Year 1
      XXX
      返回 Year 1。但是您需要检查 td 是否为空 if(cell.ChildNodes.Count > 0) { //get text here }
    • 如何排除某些 tr?在我的 HTML 中,在 tr[5] 行中,什么都没有。因此,发生了 NullReferenceException。我试过//tr(* except tr[5])。 @derloopkat
    • @heyaa,就像我提到的 td 你可以为 tr 做的一样,添加一个 IF 语句来检查是否有子节点。另一种选择是检查 tr 的内部文本是否为空。为了忽略空格,请使用 Trim()。
    【解决方案2】:

    与上面提到的类似,使用选择器查询以循环 tr 元素,然后选择每行的固定位置 td 节点:

    假设结构如下:

    <table id="searchResultsTable">
    <tbody>
    <tr>
        <td>1</td>
        <td>Name<a>Name 1</a></td>
        <td>Year 1</td>
        <td>KM 1</td>
        <td>Color 1</td>
        <td>Price 1</td>
        <td>Date 1</td>
        <td>Location 1</td>
    </tr>
    <tr>
        <td>2</td>
        <td>Name<a>Name 2</a></td>
        <td>Year 2</td>
        <td>KM 2</td>
        <td>Color 2</td>
        <td>Price 2</td>
        <td>Date 2</td>
        <td>Location 2</td>
    </tr>
    </tbody>
    

    示例:

    var document = new HtmlDocument();
    document.Load("example.html");
    
    var rows = document.DocumentNode.SelectNodes("//*[@id='searchResultsTable']/tbody/tr");
    
    foreach(var row in rows)
    {
        var name = row.SelectSingleNode("td[2]/a[1]").InnerText;
        var year = row.SelectSingleNode("td[3]").InnerText;
        var km = row.SelectSingleNode("td[4]").InnerText;
        var color = row.SelectSingleNode("td[5]").InnerText;
        var price = row.SelectSingleNode("td[6]").InnerText;
        var date = row.SelectSingleNode("td[7]").InnerText;
        var location = row.SelectSingleNode("td[8]").InnerText;
    
        Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}, {6}", name, year, km, color, price, date, location);
    }
    

    生产:

    Name 1, Year 1, KM 1, Color 1, Price 1, Date 1, Location 1
    Name 2, Year 2, KM 2, Color 2, Price 2, Date 2, Location 2
    

    【讨论】:

    • 我尝试了您的解决方案。我不知道为什么,但我只得到了 3 个 tr。 @JohnL
    • 我明白为什么我只得到 3 trs。因为 tr[4] 是空的。
    猜你喜欢
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多