HTML Agility Pack-テーブルの解析
-
19-08-2019 - |
質問
HTMLアジリティパックを使用して複雑なWebページのテーブルを解析したいのですが、オブジェクトモデルで何らかの形で失われています。
リンクの例を見てみましたが、この方法ではテーブルデータが見つかりませんでした。
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拡張機能をインストールすることです。Firebugを起動するには、サイト/ウェブページF12を押してください。クエリするページ上の要素を右クリックして右クリックし、<!> quot; Inspect Element <!> quot;を選択します。 FirebugはIDEで要素を選択し、Firebugの要素を右クリックして<!> quot; Copy XPath <!> quot;を選択します。この関数は、HTML Agility Libraryを使用して必要な要素を取得するために必要な正確なXPathクエリを提供します。
これはかなり古い質問であることはわかっていますが、これはテーブルを視覚化してクラス構造を作成できるようにした私の解決策でした。これも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は、ヘッダーとデータをプロパティとして持つ単純なオブジェクトです。 アプローチはnull-nessとこのケースを処理します:
<tr>
<td width="28%"> </td>
</tr>
ヘッダーのない行です。ぶら下がる定数を持つHtmlBodyオブジェクトはおそらく容易に推測されますが、それでもなお謝罪します。私はあなたが<!> quotを持っている世界から来ました。コードでは、定数またはローカライズ可能にする必要があります。
上記の回答の行:
HtmlDocument doc = new HtmlDocument();
これはVS 2015 C#では機能しません。 HtmlDocument
をこれ以上構築することはできません。
別のMS <!> quot; feature <!> quot;それは物事をより使いにくくします。 HtmlAgilityPack.HtmlWeb
を試して、このリンク一部のサンプルコード。