1

这篇文章的延续,我正在尝试从 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 条信息:Queue 下面的 td 内的数据和 Wait 下面的 td 内的数据(因此是 Queue 计数和等待时间)。显然,这些数字会经常更新。

我已经到了将 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.
     */
}

我可以通过 a 完成此操作foreach,但我不确定如何访问该值或如何获取下一个值。

4

2 回答 2

3

一般来说,没有必要通过 aforeach来获取目标信息非常容易(使用 aforeach你必须管理循环的每次迭代的状态,这真的很笨拙)。

首先,你想拿到桌子。过滤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包装内容的标签,但您希望元素中的所有文本都是完整的,您可以使用该属性来获取值:tdInnerText

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

注意,这里有复制,所以如果你发现有很多行需要像这样解析,你可能需要将一些逻辑分解到辅助方法中。

于 2012-12-18T18:44:52.803 回答
1

您也可以使用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
}
于 2012-12-18T19:35:04.773 回答