Ottieni dati usando HAP (HTML Agility Pack) dalla pagina

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

Domanda

Una continuazione di questo post , sto cercando di analizzare alcuni dati da una pagina HTML. Ecco l'HTML (ci sono più informazioni sulla pagina, ma questa è la sezione importante):

<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>

Ho bisogno di ottenere 2 informazioni: i dati all'interno del td in coda e i dati all'interno del td in basso Wait (quindi il conteggio della coda e il tempo di attesa). Ovviamente i numeri si aggiorneranno frequentemente.

Sono arrivato al punto in cui l'HTML è caricato in una variabile HtmlDocument. E ho trovato qualcosa sulla falsariga di utilizzare un HtmlNodeCollection per raccogliere nodi che soddisfano determinati criteri. Questo è fondamentalmente dove sono bloccato:

<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>

E posso passare attraverso questo con un foreach , ma non sono sicuro di come accedere al valore o come ottenere il valore successivo.

Risposta accettata

Generalmente, non è necessario eseguire una foreach poiché ottenere le informazioni mirate è piuttosto semplice (con un foreach dovresti gestire lo stato di ogni iterazione del ciclo ed è davvero poco maneggevole).

Per prima cosa, vuoi prendere il tavolo. Il filtro sull'attributo della class è in genere una cattiva idea, in quanto è possibile avere più elementi in un documento HTML a cui è stata applicata la classe. Se avessi un attributo id , sarebbe l'ideale.

Detto questo, se questa è l'unica tabella con questa classe, allora puoi ottenere il corpo dell'elemento della table usando:

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

Da lì, vuoi ottenere le singole righe. Poiché questi sono figli diretti dell'elemento tbody , puoi ottenere le righe in base alla posizione attraverso la proprietà ChildNodes , in questo modo:

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

Quindi vuoi il secondo elemento td in ogni riga. Mentre c'è un tag span che avvolge il contenuto, vuoi tutto il testo che è nell'elemento td nella sua interezza, puoi usare la proprietà InnerText per ottenere il valore:

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

Nota, c'è la replica qui, quindi se trovi che ci sono molte righe che devi analizzare in questo modo, potresti voler considerare parte della logica in metodi di supporto.


Risposta popolare

Puoi anche usare CsQuery per farlo. Poiché utilizza la sintassi del selettore CSS e i metodi jQuery, può essere più semplice da utilizzare rispetto a HAP per una navigazione DOM più complessa. Per esempio:

// 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
}



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché