2013-03-23 137 views
1

我一直在尝试一段时间,但这是我的情况;用HtmlAgilityPack读出C#中的表格

我的朋友的网络应用程序运行一个非常简单的HTML网站为图表生成数据。我想从该表中的某个值获取某些值,因为他需要将这些信息存储到数据库中。

所以这是HTML表的一部分;

... 
<tr> 
    <td width=30 align=center bgcolor=#006699 class=W><font color=white>1</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>7387</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>2</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>2881</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>3</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>8782</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>4</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>5297</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>5</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>749</td> 
</tr> 
<tr> 
    <td align=center bgcolor=#006699 class=W><font color=white>6</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>3136</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>7</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>8768</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>8</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>9548</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>9</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>6565</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>10</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>142</td> 
</tr> 
... 

我想达到的是;

  • 我得到两个数字 - 例如1和8
  • 我的应用程序检查页面的HTML和选择两个td(如上所示)包含数字。
  • 然后,我必须得到NEXT td的值。

这个的输出将是1=73878=9548。 我试图找到包含给定数字的两个td后,我卡住了很快。

到目前为止我的C#代码;

using (WebClient webClient = new WebClient()) 
{ 
    string completeHTMLCode = webClient.DownloadString("someUrl.php?getChartData=" + chartId); 

    HtmlDocument doc = new HtmlDocument(); 
    doc.LoadHtml(completeHTMLCode); 

    foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//td[@...]")) 
    { 

    } 
} 

我在这里尝试一些不可能的事情吗?

+0

正在添加它。抱歉。 – Roel 2013-03-23 00:42:22

+0

HTML是相当可怕的,但我认为你正在尝试听起来真的很容易。我会尽量使用CSQuery(虽然它可能会阻塞你输入中相当讨厌的HTML)。 – Nenotlep 2013-03-23 00:49:59

+0

我希望我能控制HTML。这确实很糟糕,如果你看到整个文档,你会感到震惊。我将看看CSQuery。 – Roel 2013-03-23 00:56:48

回答

3

我做了一个快速的CsQuery示例如何完成此操作。

string file = File.ReadAllText("a.html"); // gets the html 

CQ dom = file; // initializes csquery 
CQ td = dom["td"]; // get all td files 

td.Each((i,e) => { // go through each 
    if (e.FirstChild != null) // if element has child (font) 
    { 
     if (e.FirstChild.NodeType != NodeType.TEXT_NODE) // ignore text node 
     { 
      if (e.FirstChild.InnerText == "1") // if number is 1 
      { 
       Console.WriteLine(e.NextElementSibling.InnerText); // output the text 
      } 
      if (e.FirstChild.InnerText == "8") // etc etc 
      { 
       Console.WriteLine(e.NextElementSibling.InnerText); 
      } 
     } 
    } 

}); 

Console.ReadKey(); 
+0

CSQuery看起来像HTMLAgilityPack的一个有趣替代品。我会调查它。感谢您的建议。 – 2013-03-23 01:30:13

+1

这真是太神奇了。非常感谢你... – Roel 2013-03-23 09:24:51

1

你可以将它解析成字典并查找它。我可以想到解析它的一些更好的方法,但这是你想要的。

void Main() 
{ 
    string html = @"<tr> 
    <td width=30 align=center bgcolor=#006699 class=W><font color=white>1</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>7387</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>2</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>2881</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>3</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>8782</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>4</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>5297</td> 

    <td width=30 height=25 align=center bgcolor=#006699 class=W><font color=white>5</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>749</td> 
</tr> 
<tr> 
    <td align=center bgcolor=#006699 class=W><font color=white>6</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>3136</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>7</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>8768</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>8</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>9548</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>9</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>6565</td> 

    <td height=25 align=center bgcolor=#006699 class=W><font color=white>10</font></td> 
    <td width=50 bgcolor=#FFFFFF align=center>142</td> 
</tr>"; 

    HtmlDocument doc = new HtmlDocument(); 
    doc.LoadHtml(html); 

    int[] nodes = doc.DocumentNode.SelectNodes("//td").Select (dn => 
     int.Parse(dn.InnerHtml.Contains("font") ? dn.FirstChild.InnerHtml : dn.InnerHtml) 
     ).ToArray(); 

    Dictionary<int,int> d = new Dictionary<int,int>(); 
    for (int i = 0; i < nodes.Length; i+=2) 
     d.Add(nodes[i],nodes[i+1]); 

    d.Dump(); 
    d[1].Dump(); 
    d[8].Dump(); 
} 
0

那么,如果你只有这个表的数据可以使用它与HTMLAgilityPack解析。

我要做的第一件事就是不要使用foreach遍历tds,我会使用计数器,然后使用counter id作为索引器。代码可能看起来像这样

for(int i = 1;i <= selectednodes.Count();i++) 
{ 
    if(selectednodes[i-1].InnerHtml.Contains("font") 
    { 
    if(selectednodes[i-1].FirstChild.Value == "1" || selectednodes[i-1].FirstChild.Value == "8") 
    { 
     myNodecollection.Add(selectednodes[i]) 
    } 
    } 
}