Получить данные с помощью HAP (HTML Agility Pack) со страницы

.net .net-4.0 c# html-agility-pack

Вопрос

Продолжая этот пост , я пытаюсь разобрать некоторые данные с HTML-страницы. Вот HTML (есть больше информации на странице, но это важный раздел):

<table class="integrationteamstats">
<tbody>
<tr>
    <td class="right">
        <span class="mediumtextBlack">Queue:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0</span>
    </td>
    <td class="right">
        <span class="mediumtextBlack">Aban:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0%</span>
    </td>
    <td class="right">
        <span class="mediumtextBlack">Staffed:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0</span>
    </td>
</tr>
<tr>
    <td class="right">
        <span class="mediumtextBlack">Wait:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0:00</span>
    </td>
    <td class="right">
        <span class="mediumtextBlack">Total:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0</span>
    </td>
    <td class="right">
        <span class="mediumtextBlack">On ACD:</span>
    </td>
    <td class="left">
        <span class="mediumtextBlack">0</span>
    </td>
</tr>
</tbody>
</table>

Мне нужно получить 2 части информации: данные внутри td ниже очереди и данные внутри td ниже Wait (поэтому количество очереди и время ожидания). Очевидно, что цифры будут часто обновляться.

Я дошел до того, что HTML заносится в переменную HtmlDocument. И я нашел что-то вроде использования HtmlNodeCollection для сбора узлов, соответствующих определенным критериям. Это в основном, где я застрял:

HtmlNodeCollection tds = 
    new HtmlNodeCollection(this.html.DocumentNode.ParentNode);
tds = this.html.DocumentNode.SelectNodes("//td");

foreach (HtmlNode td in tds)
{
    /* I want to write:
     * If the last node's value was 'Queue', give me the value of this node.
     * and
     * If the last node's value was 'Wait Time', give me the value of this node.
     */
}

И я могу пройти через это с помощью foreach , но я не уверен, как получить доступ к значению или как получить следующее значение.

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

Как правило, нет необходимости проходить через foreach поскольку получение целевой информации довольно просто (с помощью foreach вам нужно будет управлять состоянием каждой итерации цикла, и это действительно громоздко).

Сначала вы хотите получить таблицу. Фильтрация атрибута class обычно является плохой идеей, так как вы можете иметь несколько элементов в документе HTML, к которым применяется класс. Если бы у вас был атрибут id , это было бы идеально.

Тем не менее, если это единственная таблица с этим классом, вы можете получить тело элемента table используя:

// Get the table.
HtmlNode tableBody = document.DocumentNode.SelectSingleNode(
    "//table[@class='integrationteamstats']/tbody");

Оттуда вы хотите получить отдельные строки. Поскольку это прямые дочерние элементы элемента tbody , вы можете получить строки по позиции через свойство ChildNodes , например:

HtmlNode queueRow = tableBody.ChildNodes[0];
HtmlNode waitRow = tableBody.ChildNodes[1];

Затем вам нужен второй td элемент в каждой строке. Хотя там есть тег span который обертывает содержимое, вы хотите, чтобы весь текст, находящийся в элементе td , целиком, вы можете использовать свойство InnerText для получения значения:

string queueValue = queueRow.ChildNodes[1].InnerText;
string waitValue = waitRow.ChildNodes[1].InnerText;

Обратите внимание, что здесь есть репликация, поэтому, если вы обнаружите, что есть много строк, которые вам нужно разобрать таким образом, вам может понадобиться отделить часть логики от вспомогательных методов.


Популярные ответы

Вы также можете использовать CsQuery для этого. Поскольку он использует знакомый синтаксис селектора CSS и методы jQuery, его можно будет проще использовать, чем HAP для более сложной навигации по DOM. Например:

// function to get the text from the cell AFTER the one containing 'text'

string getNextCellText(CQ dom, string text) {
    // find the target cell
    CQ target= dom.Select(".integrationteamstats td:contains(" + text + ")");

    // return the text contents of the next cell
    return target.Next().Text();
}

void Main() {
    var dom = CQ.Create(html);
    string queue = getNextCellText(dom,"Queue");
    string wait = getNextCellText(dom,"Wait:");

    .. do stuff
}


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