web-dev-qa-db-fra.com

Pack d'agilité HTML - tables d'analyse

Je souhaite utiliser le pack d'agilité HTML pour analyser des tables à partir de pages Web complexes, mais je suis en quelque sorte perdu dans le modèle d'objet.

J'ai regardé l'exemple de lien, mais je n'ai trouvé aucune donnée de table de cette façon ..__ Puis-je utiliser XPath pour obtenir les tables? Je suis fondamentalement perdu après avoir chargé les données sur la manière d'obtenir les tables. Je l'avais déjà fait auparavant avec Perl et c'était un peu maladroit, mais cela fonctionnait. (HTML::TableParser). 

Je suis également heureux si l'on peut simplement éclaircir le bon ordre d'objet pour l'analyse.

51
weismat

Pourquoi pas quelque chose comme: Using HTML Agility Pack

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(@"<html><body><p><table id=""foo""><tr><th>hello</th></tr><tr><td>world</td></tr></table></body></html>");
foreach (HtmlNode table in doc.DocumentNode.SelectNodes("//table")) {
    Console.WriteLine("Found: " + table.Id);
    foreach (HtmlNode row in table.SelectNodes("tr")) {
        Console.WriteLine("row");
        foreach (HtmlNode cell in row.SelectNodes("th|td")) {
            Console.WriteLine("cell: " + cell.InnerText);
        }
    }
}

Notez que vous pouvez le rendre plus joli avec LINQ-to-Objects si vous voulez:

var query = from table in doc.DocumentNode.SelectNodes("//table").Cast<HtmlNode>()
            from row in table.SelectNodes("tr").Cast<HtmlNode>()
            from cell in row.SelectNodes("th|td").Cast<HtmlNode>()
            select new {Table = table.Id, CellText = cell.InnerText};

foreach(var cell in query) {
    Console.WriteLine("{0}: {1}", cell.Table, cell.CellText);
}
111
Marc Gravell

Le plus simple que j'ai trouvé pour obtenir le XPath pour un élément particulier est d'installer l'extension FireBug pour Firefox. Allez sur le site/la page Web. Appuyez sur F12 pour afficher Firebug; sélectionnez à droite, cliquez avec le bouton droit sur l'élément de la page que vous souhaitez interroger et sélectionnez "Inspecter l'élément". Firebug sélectionnera l'élément dans son IDE, puis cliquez avec le bouton droit sur l'élément dans Firebug et choisissez "Copier XPath". la requête XPath exacte dont vous avez besoin pour obtenir l'élément souhaité à l'aide de HTML Agility Library.

31
Coda

Je sais que c’est une question assez ancienne, mais c’était ma solution qui permettait de visualiser le tableau afin de créer une structure de classe. Ceci utilise également le HTML Agility Pack

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(@"<html><body><p><table id=""foo""><tr><th>hello</th></tr><tr><td>world</td></tr></table></body></html>");
var table = doc.DocumentNode.SelectSingleNode("//table");
var tableRows = table.SelectNodes("tr");
var columns = tableRows[0].SelectNodes("th/text()");
for (int i = 1; i < tableRows.Count; i++)
{
    for (int e = 0; e < columns.Count; e++)
    {
        var value = tableRows[i].SelectSingleNode($"td[{e + 1}]");
        Console.Write(columns[e].InnerText + ":" + value.InnerText);
    }
Console.WriteLine();
}
1
B. Miller

Dans mon cas, il existe une seule table qui se trouve être une liste de périphériques d'un routeur. Si vous souhaitez lire le tableau en utilisant TR/TH/TD (ligne, en-tête, données) au lieu d'une matrice comme indiqué ci-dessus, vous pouvez procéder comme suit:

    List<TableRow> deviceTable = (from table in document.DocumentNode.SelectNodes(XPathQueries.SELECT_TABLE)
                                       from row in table?.SelectNodes(HtmlBody.TR)
                                       let rows = row.SelectSingleNode(HtmlBody.TR)
                                       where row.FirstChild.OriginalName != null && row.FirstChild.OriginalName.Equals(HtmlBody.T_HEADER)
                                       select new TableRow
                                       {
                                           Header = row.SelectSingleNode(HtmlBody.T_HEADER)?.InnerText,
                                           Data = row.SelectSingleNode(HtmlBody.T_DATA)?.InnerText}).ToList();
                                       }  

TableRow est juste un objet simple avec en-tête et données en tant que propriétés . L'approche prend en charge la nullité et ce cas:

<tr>
    <td width="28%">&nbsp;</td>
</tr>

qui est rangée sans en-tête. On en déduit probablement les objets HtmlBody avec les constantes pendantes, mais je m'en excuse encore. Je viens du monde où vous avez "dans votre code, il devrait être soit constant, soit localisable. 

0
Shibumi Tait