从HTML表中存储数据的最佳方法是什么?

时间:2014-02-11 11:46:25

标签: c# html csquery

我目前正在使用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对象的方法,所以我需要先确定它的公式。

4 个答案:

答案 0 :(得分:2)

  

是否有更好的方法来存储这些数据,因此我可以轻松访问特定的表,特定的行和单元格?

在大多数情况下,格式良好的HTML非常适合XML结构,因此您可以将其存储为XML文档。 LINQ to XML将使查询非常简单

XDocument doc = XDocument.parse("<html>...</html>");
var cellData = doc.Descendant("td").Select(x => x.Value);

基于这些评论,我觉得有必要指出,还有其他几种可能会出现的情况,例如

  • 使用像&nbsp;这样的HTML编码内容
  • 有效的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表格是一致的,我宁愿采用这样的方法来实现与框架其余部分的互操作性,而且工作量也会减少。