HTML Parsing C # HTMLAgilityPack

c# html-agility-pack xpath

Вопрос

У меня проблема с чтением некоторых значений из строки HTML с помощью HTMLAgilityPack.

Два предмета, которые я хочу прочитать, это газета: 82548828 и рыба: 8545852485

Но с использованием кода, который я написал до сих пор, я могу только вернуть элемент газеты.

Я подозреваю, что XPATH, который я использую, не совсем корректен, я думаю, что XPATH для первого цикла является правильным, так как это возвращает мне два

Я хочу, чтобы мой второй цикл зациклился на этих двух элементах (он думает, что есть 6 ???)

Также div2.SelectSingleNode (sXPathT); правильный способ извлечения groupLabel? или есть лучший способ?

благодаря

Полный тестовый код ниже

string strTestHTML = @"<div class=\""content\"" data-id=\""123456789\"">" + 
                              "  <div class=\"m-group item\">" +
                              "      <span class=\"group\">" +
                              "          <a href=\"javascript:void(0);\">" +
                              "          <span class=\"group-label\">Newspaper </span>" +
                              "          <span class=\"group-value\">82548828</span>" +
                              "          </a>" +
                              "      </span>" +
                              "      <span class=\"group\">" +
                              "          <a href=\"javascript:void(0);\">" +
                              "          <span class=\"group-label\">Fish </span>" +
                              "          <span class=\"group-value\">8545852485</span>" +
                              "          </a>" +
                              "      </span>" +
                              "  </div>" +
                              "</div>";


            //<div class="content" data-id="123456789">
            string sNewXpath = "//div[contains(@class,'content') and contains(@data-id, '" + "123456789" + "')]";
            //<div class="m-group item">
            string sSecondXPath = "/div[contains(@class,'m-group item')]";
            //<span class="group"
            string sThirdXPath = "//span[contains(@class,'group')]";

            string sXPathT = "//span[contains(@class,'group-label')]";
            string sXPathO = "//span[contains(@class,'group-value')]";

            HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
            Doc.LoadHtml(strTestHTML);

            foreach (HtmlNode div in Doc.DocumentNode.SelectNodes(sNewXpath + sSecondXPath))
            {
                foreach (HtmlNode div2 in div.SelectNodes(sThirdXPath))
                {
                    var vOddL = div2.SelectSingleNode(sXPathT);
                    var vOddP = div2.SelectSingleNode(sXPathO);

                    string GroupLabel = vOddL.InnerText.Trim();

                    string GroupValue = vOddP.InnerText.Trim();
                }
            }

РЕДАКТИРОВАТЬ:

Выяснилось, почему я получал 6 предметов обратно в forloop

sThirdXPath: string sThirdXPath = "// span [contains (@ class, 'group')]";

должно быть:

string sThirdXPath = "// span [@ class = 'group']";

Все еще пытаясь найти правильный способ опроса HTMLNode, содержащегося в div2, чтобы найти интересующие ценности. Я предполагаю, что XPath должен соответствовать iinside текущего узла, а не HTML-документа в целом.

Обновленный образец HTML:

<div class="content" data-id="123456789">
<div class="m-group item">
    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Newspaper </span>
        <span class="group-value">82548828</span>
        </a>
    </span>

    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Fish </span>
        <span class="group-value">8545852485</span>
        </a>
    </span>
</div>
</div>

<div class="content" data-id="987654321">
<div class="m-group item">
    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Bread</span>
        <span class="group-value">82548828</span>
        </a>
    </span>

    <span class="group">
        <a href="javascript:void(0);">
        <span class="group-label">Milk </span>
        <span class="group-value">8545852485</span>
        </a>
    </span>
</div>
</div>

В приведенном выше примере, какой правильный XPATH для доступа к Just Bread и его стоимости и молока и его стоимости. Я предполагаю, что мне нужно фильтровать на data-id = "987654321 в XPath?

Принятый ответ

Ваше подозрение верное, вы уже указали запросы XPath для полного пути, поэтому вам не нужен цикл. Чтобы получить узлы «Газета» и «Рыба» в этом примере, вы можете просто использовать SelectNodes вместо цикла и вызова SelectSingleNode. Если есть больше элементов, вы можете, конечно, прокручивать результирующий набор, я обратился к ним по индексу в этом примере, так как их только два.

string sXPathT = "//span[contains(@class,'group-label')]";
string sXPathO = "//span[contains(@class,'group-value')]";

HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
Doc.LoadHtml(strTestHTML);

var vOddL = Doc.DocumentNode.SelectNodes(sXPathT);
var vOddP = Doc.DocumentNode.SelectNodes(sXPathO);

string GroupLabelNewsPaper = vOddL.ElementAt(0).InnerText.Trim();
string GroupLabelFish = vOddL.ElementAt(1).InnerText.Trim();

string GroupValueNewspaper = vOddP.ElementAt(0).InnerText.Trim();
string GroupValueFish = vOddP.ElementAt(1).InnerText.Trim();

Console.WriteLine($"{GroupLabelNewsPaper}\t{GroupValueNewspaper}");
Console.WriteLine($"{GroupLabelFish}\t{GroupValueFish}");

Вывод:

Newspaper       82548828
Fish    8545852485

UPDATE: для получения определенного узла контента вы можете использовать этот XPath:

string xpathForDataId = "//div[@class='content' and @data-id='987654321']";

Вы можете отфильтровать div с указанным выше выражением, а затем получить дочерние узлы этого типа:

string sXPathT = ".//span[contains(@class,'group-label')]";
string sXPathO = ".//span[contains(@class,'group-value')]";
string xpathForDataId = "//div[@class='content' and @data-id='987654321']";

HtmlAgilityPack.HtmlDocument Doc = new HtmlDocument();
Doc.LoadHtml(strTestHTML);

var specificNode = Doc.DocumentNode.SelectSingleNode(xpathForDataId);

var vOddL = specificNode.SelectNodes(sXPathT);
var vOddP = specificNode.SelectNodes(sXPathO);

string GroupLabelBread = vOddL.ElementAt(0).InnerText.Trim();
string GroupLabelMilk = vOddL.ElementAt(1).InnerText.Trim();

string GroupValueBread = vOddP.ElementAt(0).InnerText.Trim();
string GroupValueMilk = vOddP.ElementAt(1).InnerText.Trim();

Console.WriteLine($"{GroupLabelBread}\t{GroupValueBread}");
Console.WriteLine($"{GroupLabelMilk}\t{GroupValueMilk}");

Обратите внимание на «.//» в sXPathT и sXPathO. При этом мы ищем только текущий контекст, а не весь документ.

Вывод:

Bread   82548828
Milk    8545852485


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему