HTML 敏捷包

3

我在一个网页中有HTML表格,如下所示:

<table border=1>
    <tr><td>sno</td><td>sname</td></tr>
    <tr><td>111</td><td>abcde</td></tr>
    <tr><td>213</td><td>ejkll</td></tr>
</table>

<table border=1>
    <tr><td>adress</td><td>phoneno</td><td>note</td></tr>
    <tr><td>asdlkj</td><td>121510</td><td>none</td></tr>
    <tr><td>asdlkj</td><td>214545</td><td>none</td></tr>
</table>

现在我想使用Html Agility Pack从这个网页中提取地址和电话号码两列的数据。也就是说,我要确定哪个表格中有地址和电话号码这两列。找到该表格后,我想要提取该表格中地址和电话号码这两列的数据,应该怎么做?
我可以获取到表格,但之后不知道该怎么做。
另外一个问题是:我们是否能够通过列名从表格中提取数据?

这是一个重复的链接,与https://dev59.com/KEzSa4cB1Zd3GeqPnH9y相同。 - Mike Two
1
@Harikrishna - 这是你昨天问的同样问题。你在昨天的问题中已经表明了这个要求。这仍然是一个重复的问题。如果你让原始问题更清晰,而不是添加新问题,那么这确实更容易。这样你更有可能得到你想要的答案。 - Mike Two
@Harikrishna - 我理解你对我给出的答案的问题,我不反对,但是再次问同样的问题并不是获得更好答案的方式。 - Mike Two
@Mike Two先生,非常感谢您对我之前问题的帮助。 - Harikrishna
@Harikrishna - 不客气,希望有所帮助。祝你的项目好运。 - Mike Two
2个回答

4
以下是一些辅助方法,可以帮助您将HTML表格解析为DataTable实例。只需遍历生成的DataTable数组以找到包含所需列的那个。此代码与HTML中表格的格式耦合,例如它从第一行(<tr>)获取列信息。还请注意,没有执行任何错误检查,因此不符合您指定的格式的表格会出现问题。
private static DataTable[] ParseAllTables(HtmlDocument doc)
{
    var result = new List<DataTable>();
    foreach (var table in doc.DocumentNode.Descendants("table"))
    {
        result.Add(ParseTable(table));
    }
    return result.ToArray();
}

private static DataTable ParseTable(HtmlNode table)
{
    var result = new DataTable();

    var rows = table.Descendants("tr");

    var header = rows.Take(1).First();
    foreach (var column in header.Descendants("td"))
    {
        result.Columns.Add(new DataColumn(column.InnerText, typeof(string)));
    }

    foreach (var row in rows.Skip(1))
    {
        var data = new List<string>();
        foreach (var column in row.Descendants("td"))
        {
            data.Add(column.InnerText);
        }
        result.Rows.Add(data.ToArray());
    }
    return result;
}

使用示例:

public static void Main(string[] args)
{
    string html = @"
        <html><head></head>
        <body><div>
            <table border=1>
                <tr><td>sno</td><td>sname</td></tr>
                <tr><td>111</td><td>abcde</td></tr>
                <tr><td>213</td><td>ejkll</td></tr>
            </table>
            <table border=1>
                <tr><td>adress</td><td>phoneno</td><td>note</td></tr>
                <tr><td>asdlkj</td><td>121510</td><td>none</td></tr>
                <tr><td>asdlkj</td><td>214545</td><td>none</td></tr>
            </table>
        </div></body>
        </html>";

    HtmlDocument doc = new HtmlDocument();

    doc.LoadHtml(html);

   DataTable addressAndPhones;
   foreach (var table in ParseAllTables(doc))
   {
       if (table.Columns.Contains("phoneno") && table.Columns.Contains("adress"))
       {
           // You found the address and phone number table
           addressAndPhones = table;
       }
   }
}

@Harikrishna,SkipTakeSystem.Linq中定义。您需要为该命名空间添加一个using语句。LINQ在.NET 2.0中不可用。 - João Angelo
@Harikrishna,正如我所说的,这些辅助函数与给定的HTML格式高度耦合。它们适用于以下示例。如果您有不同的输入,则必须根据您的需求进行调整。 - João Angelo
@Joao Angelo..感谢你的帮助。由于在html agility包中没有选项,所以现在我正在使用html tidy包来补全缺失的关闭标签。 - Harikrishna
@Joao Angelo,我有一个主要的问题,已经尝试解决很多天了。有时候HTML页面可能像表格一样不以列标题开头,而是以其他信息开头,我想跳过它们,但是会出现错误:列的FillWeight值之和不能超过65535。 - Harikrishna
@Joao Angelo,如果表格标签是最内层的,例如<table><tr><td></td><td><table><tr><td><td><table><tr><td><table>。那么我想提取最内层的表格。 - Harikrishna
显示剩余3条评论

1

循环遍历表格行并通过索引获取列值

int index = 0;
foreach(HtmlNode tablerow in table.SelectNodes("tr"))
{
    // skip the first row...
    if(index > 0)
    {
        // select first td element
        HtmlNode td1 = tablerow.SelectSingleNode("td[1]");
        if(td1 != null)
        {
            string address = td1.InnerText;
        }
    }
    index++;
}

如果您可以修改网页,您可以使用thead来设置表头文本,使用tbody来显示实际数值。
<table id="mytable">
    <thead><tr><td>Column1</td><td>Column2</td></tr></thead>
    <tbody>
        <tr><td>Value 1</td><td>Value 2</td></tr>
        <tr><td>Value 1</td><td>Value 2</td></tr>
    </tbody>
</table>

那么你就不必跳过第一行了。

foreach(HtmlNode tablerow in table.SelectNodes("/table[@id=\"mytable\"]/tbody/tr")){    // ...}

看一下一些XPath教程,它与HtmlAgilityPack非常有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接