我目前正在使用CsQuery阅读HTML文档。这个文档有几个HTML表,我需要在保留结构的同时读入数据。目前,我只是有一个字符串列表列表。这是一个包含行列表的表列表,其中包含包含内容作为字符串的单元格列表。
List<List<List<string>>> page_tables = document_div.Cq().Find("TABLE")
.Select(table => table.Cq().Find("TR")
.Select(tr => tr.Cq().Find("td")
.Select(td => td.InnerHTML).ToList())
.ToList())
.ToList();
有没有更好的方法来存储这些数据,因此我可以轻松访问特定的表,特定的行和单元格?我正在写几个处理这个page_tables对象的方法,所以我需要先确定它的公式。
答案 0 :(得分:2)
是否有更好的方法来存储这些数据,因此我可以轻松访问特定的表,特定的行和单元格?
在大多数情况下,格式良好的HTML非常适合XML结构,因此您可以将其存储为XML文档。 LINQ to XML将使查询非常简单
XDocument doc = XDocument.parse("<html>...</html>");
var cellData = doc.Descendant("td").Select(x => x.Value);
基于这些评论,我觉得有必要指出,还有其他几种可能会出现的情况,例如
这样的HTML编码内容<br>
(话虽如此,这些东西可以通过一些预处理来处理)
总而言之,它绝不是最强大的健壮的方法,但是,如果您可以确定您正在解析的HTML符合要求,那么它将是一个非常简洁的解决方案。
答案 1 :(得分:1)
您可以完全使用OOP并编写一些模型类:
// Code kept short, minimal ctors
public class Cell
{
public string Content {get;set;}
public Cell() { this.Content = string.Empty; }
}
public class Row
{
public List<Cell> Cells {get;set;}
public Row() { this.Cells = new List<Cell>(); }
}
public class Table
{
public List<Row> Rows {get;set;}
public Table() { this.Rows = new List<Row>(); }
}
然后填写它们,例如:
var tables = new List<Table>();
foreach(var table in document_div.Cq().Find("TABLE"))
{
var t = new Table();
foreach(var tr in table.Cq().Find("TR"))
{
var r = new Row();
foreach(var td in tr.Cq().Find("td"))
{
var c = new Cell();
c.Contents = td.InnerHTML;
r.Cells.Add(c);
}
t.Rows.Add(r);
}
tables.Add(t);
}
// Assuming the HTML was correct, now you have a cleanly organized
// class structure representing the tables!
var aTable = tables.First();
var firstRow = aTable.Rows.First();
var firstCell = firstRow.Cells.First();
var firstCellContents = firstCell.Contents;
...
我可能会选择这种方法,因为我总是更愿意确切知道我的数据是什么样的,特别是当我从外部/不安全/不可靠的源解析时。
答案 2 :(得分:0)
是否有更好的方法来存储此数据,因此我可以轻松访问 特定的表,特定的行和单元格?
如果要轻松访问表数据,则创建一个类,该类将保存表行中的数据,并为相应的列提供具有良好命名的属性。例如。如果你有用户表
<table>
<tr><td>1</td><td>Bob</td></tr>
<tr><td>2</td><td>Joe</td></tr>
</table>
我会创建以下类来保存行数据:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
第二步是从HTML解析用户。我建议使用HtmlAgilityPack(可从NuGet获得)来解析HTML:
HtmlDocument doc = new HtmlDocument();
doc.Load("index.html");
var users = from r in doc.DocumentNode.SelectNodes("//table/tr")
let cells = r.SelectNodes("td")
select new User
{
Id = Int32.Parse(cells[0].InnerText),
Name = cells[1].InnerText
};
// NOTE: you can check cells count before accessing them by index
现在您拥有强类型用户对象的集合(您可以将它们保存到列表,数组或字典 - 这取决于您将如何使用它们)。 E.g。
var usersDictionary = users.ToDictionary(u => u.Id);
// Getting user by id
var user = usersDictionary[2];
// now you can read user.Name
答案 3 :(得分:0)
自解析HTML表格以来。你能使用ADO.Net DataTable吗?如果内容没有太多的行或列,这可能是一个选项,您不必自己滚动,它可以很容易地保存到数据库或实体列表或其他任何内容。此外,您还可以获得强类型数据类型的好处。只要HTML表格是一致的,我宁愿采用这样的方法来实现与框架其余部分的互操作性,而且工作量也会减少。