html - 将 html 表解析为数据集时出错

标签 html vb.net winforms html-table html-agility-pack

我正在尝试将表格从 html 文件解析为数据集。我使用 vb.net 创建了一个 Windows 应用程序,我正在使用以下函数:

Public Function GetDataSet(ByVal strWebFilePath As String) As DataSet

    Dim html As String = System.IO.File.ReadAllText(strWebFilePath)

    html = WebUtility.HtmlDecode(html)

    Dim dsHtml As New DataSet
    Dim htmldoc As New HtmlAgilityPack.HtmlDocument
    htmldoc.LoadHtml(html)

    Dim tables = htmldoc.DocumentNode.SelectNodes("//table//tr") _
                    .GroupBy(Function(x) x.Ancestors("table").First())

    For i As Integer = 0 To tables.Count - 1
        Dim rows = tables(i).ToList()
        dsHtml.Tables.Add(String.Format("Table {0}", i))

        Dim headers = rows(0).Elements("th").Select(Function(x) x.InnerText.Trim).ToList()

        If headers.Count > 0 Then

            For Each Hr In headers
                dsHtml.Tables(i).Columns.Add(Hr)
            Next

            For j As Integer = 1 To rows.Count - 1
                Dim row = rows(j)
                Dim dr = row.Elements("td").Select(Function(x) x.InnerText.Trim).ToArray()
                dsHtml.Tables(i).Rows.Add(dr)
            Next

        Else

            headers = rows(0).Elements("td").Select(Function(x) x.InnerText.Trim).ToList()

            For ColumnIndex As Integer = 0 To headers.Count - 1
                dsHtml.Tables(i).Columns.Add("F" & ColumnIndex.ToString)
            Next

            For j As Integer = 0 To rows.Count - 1
                Dim row = rows(j)
                Dim dr = row.Elements("td").Select(Function(x) x.InnerText.Trim).ToArray()
                dsHtml.Tables(i).Rows.Add(dr)
            Next


        End If

    Next

    Return dsHtml
End Function

一切正常,直到我解析 html 表,它的第一行包含一个具有 colspan=2 的列(第一行被认为是标题,即使它不包含 <th> )。所以它抛出这个异常:

An unhandled exception of type 'System.ArgumentException' occurred in System.Data.dll Additional information: Input array is longer than the number of columns in this table.

考虑这个表格示例:

<table>
<tr><td colspan=2>Links</td></tr>
<tr><td>1</td><td>www.stackoverflow.com</td></tr>
<tr><td>2</td><td>www.sqlservercentral.com</td></tr>
<tr><td>3</td><td>www.dba.stackexchange.com/</td></tr>
</table>

有没有办法将第一行分成两列:

  • 第一个包含Links
  • 第二个包含自动生成的值(即:Col1)

最佳答案

您需要一些关于如何解决列跨度、行跨度、缺失单元格、额外单元格、单元格中的值不一致等问题的约定。通常很难将 html 表解析为 DataTable不知道数据表的结构。

在这个答案中,我将重点关注标题上的列跨度。

有什么问题?

你依赖<th>排在第一位 <tr>并根据找到的 <th> 添加列到数据表中.所以如果你有这样的表:

<table>
    <tr>
        <th colspan="2">A</th>
        <th>B</th>
    </tr>
    <tr>
        <td>1</td>
        <td>11</td>
        <td>111</td>
    </tr>
</table>

然后您假设您有 2 列,并且在添加行时,由于每行中有 3 个元素,您会收到异常。

我该如何解决这个问题?

这里我决定转换<th colspan="n">C</th>到名称为 C1 的 n 列, C2 , ... , Cn .

Dim headers = rows(0).Elements("th").Select(Function(x) _
    New With
    {
        .Name = x.InnerText.Trim,
        .Count = If(x.Attributes("colspan") Is Nothing, _
            1, Integer.Parse(x.Attributes("colspan").Value))
    }).ToList()

然后在向数据表中添加列时:

For Each Hr In headers
    For index = 1 To Hr.Count
        Dim postFix = If(Hr.Count > 1, index.ToString(), "")
        dsHtml.Tables(i).Columns.Add(Hr.Name & postFix)
    Next
Next

关于html - 将 html 表解析为数据集时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40852390/

相关文章:

javascript - 为什么我的图像在 HTML 页面中加载不一致?

javascript - 在正确的图层上获取 particles.js?

c# - 需要初始化对象的新实例

vb.net - 如何在 VB.NET 2013(Visual Studio 2013)中使用 Crystal 报表

.net - 文件夹重定向处于事件状态时解析 'Environment.SpecialFolder.Personal'

html - 第一个 div 使所有其他 div 移出位置

javascript - 基于先前选择的动态选择框

asp.net - 将查询字符串添加到响应重定向 ASP VB.NET

vb.net - 使用 Windows 窗体执行 .exe 文件

c# - 在没有 xml 文件的情况下在 c# 中使用 log4net