HTML Agility Pack - парсинг таблиц - PullRequest
51 голосов
/ 17 марта 2009

Я хочу использовать пакет гибкости HTML для анализа таблиц со сложных веб-страниц, но я как-то теряюсь в объектной модели.

Я посмотрел пример ссылки, но не нашел данных таблицы таким образом. Могу ли я использовать XPath для получения таблиц? Я в основном потерян после загрузки данных о том, как получить таблицы. Я делал это раньше в Perl, и это было немного неуклюже, но сработало. (HTML::TableParser).

Я также рад, если можно просто пролить свет на правильный порядок объектов для анализа.

Ответы [ 5 ]

113 голосов
/ 17 марта 2009

Как насчет чего-то вроде: Использование 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);
        }
    }
}

Обратите внимание, что вы можете сделать его красивее с LINQ-to-Objects, если хотите:

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);
}
31 голосов
/ 23 июня 2010

Самое простое, что я нашел для получения XPath для конкретного элемента - это установить расширение FireBug для Firefox. Перейдите на сайт / веб-страницу, нажмите F12, чтобы вызвать firebug; выберите правой кнопкой мыши и щелкните правой кнопкой мыши на элементе на странице, которую вы хотите запросить, и выберите «Проверить элемент». Firebug выберет элемент в его IDE, затем щелкните правой кнопкой мыши элемент в Firebug и выберите «Копировать XPath», эта функция даст вам точный XPath. Сделайте запрос, чтобы получить нужный элемент с помощью библиотеки HTML Agility.

1 голос
/ 26 апреля 2019

Я знаю, что это довольно старый вопрос, но это было мое решение, которое помогло визуализировать таблицу, чтобы вы могли создать структуру классов. Это также использует 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();
}
0 голосов
/ 05 мая 2017

В моем случае есть одна таблица, представляющая собой список устройств с маршрутизатора. Если вы хотите прочитать таблицу, используя TR / TH / TD (строка, заголовок, данные) вместо матрицы, как указано выше, вы можете сделать что-то вроде следующего:

    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 - это простой объект с заголовком и данными в качестве свойств. Подход заботится о пустоте и в этом случае:

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

строка без заголовка. Объект HtmlBody с висящими на нем константами, вероятно, легко выводится, но я до сих пор извиняюсь за это. Я пришел из мира, где, если у вас есть "в вашем коде, он должен быть либо постоянным, либо локализуемым.

0 голосов
/ 13 января 2016

Строка сверху, ответ:

HtmlDocument doc = new HtmlDocument();

Это не работает в VS 2015 C #. Вы не можете построить HtmlDocument больше.

Еще одна «особенность» MS, которая делает вещи более сложными в использовании. Попробуйте HtmlAgilityPack.HtmlWeb и проверьте эту ссылку для некоторого примера кода.

...