Пакет HTML Agility — анализ таблиц
-
19-08-2019 - |
Вопрос
Я хочу использовать пакет гибкости HTML для анализа таблиц со сложными веб-страницами, но я как-то теряюсь в объектной модели.
Я посмотрел пример ссылки, но не нашел никаких табличных данных таким образом.Могу ли я использовать XPath для получения таблиц?Я практически потерялся после загрузки данных о том, как получить таблицы.Раньше я делал это в Perl, и это было немного неуклюже, но сработало.(HTML::TableParser
).
Я также рад, если кто-то сможет пролить свет на правильный порядок объектов для синтаксического анализа.
Решение
Как насчет чего-то вроде: Использование пакета 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);
}
Другие советы
Самое простое, что я нашел для получения XPath для конкретного элемента - это установить расширение FireBug для Firefox. Перейдите на сайт / веб-страницу, нажмите F12, чтобы вызвать firebug; выберите правой кнопкой мыши и щелкните правой кнопкой мыши на элементе страницы, к которому вы хотите выполнить запрос, и выберите " Inspect Element " Firebug выберет элемент в его IDE, затем щелкните правой кнопкой мыши на элементе в Firebug и выберите & Quot; Copy XPath & Quot; эта функция даст вам точный XPath-запрос, необходимый для получения нужного элемента с помощью библиотеки HTML Agility.
Я знаю, что это довольно старый вопрос, но это было мое решение, которое помогло визуализировать таблицу, чтобы вы могли создать структуру классов. Это также использует 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();
}
В моем случае есть одна таблица, которая представляет собой список устройств с маршрутизатора.Если вы хотите прочитать таблицу, используя 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 — это простой объект со свойствами Header и Data.Этот подход учитывает нулевое значение, и в этом случае:
<tr>
<td width="28%"> </td>
</tr>
это строка без заголовка.Объект HtmlBody с свисающими с него константами, вероятно, легко выводится, но я все равно извиняюсь за это.Я пришел из мира, где если в вашем коде есть ", то оно должно быть либо постоянным, либо локализуемым.
Ответ сверху:
HtmlDocument doc = new HtmlDocument();
Это не работает в VS 2015 C #. Вы не можете создать HtmlDocument
больше.
Очередной MS " функция " это делает вещи более сложными в использовании. Попробуйте HtmlAgilityPack.HtmlWeb
и проверьте эту ссылку для некоторого примера кода.