【C#】【ASP.NET】HtmlAgilityPack操作,取得網頁中的資料

網頁爬蟲、使用HtmlAgilityPack。
網頁工具 Fiddler 查詢網址與參數。

某天主管突然說公司小姐每天要上銀行網站取的相關匯率資料,
問說是不是可以有機制每天讓系統自動取得這些資料。
因此【挨踢】又出動了。
網路上查詢一下作法,參閱資料來源如下:(族繁不及備載....請見諒)
码农家园Dot Net Perls
雷克斯筆記簿 HtmlAgility 處理網頁元件
台部落 Html Agility Pack學習(一):HtmlAgilityPack類的簡單應用
確認可行後,就著手開始試作了

首先是來源資料網頁:中國銀行外匯牌價
測試接收資料頁面:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     <asp:Button ID="Button1" runat="server" Text="中國銀行匯率牌價" OnClick="Button1_Click" />
        <br></br>
      <asp:Label ID="Label1" runat="server" Text=""></asp:Label>
     <br></br>
        <asp:GridView ID="GridView1" runat="server"> </asp:GridView>
    </form>
 
    </div>
       
</body>
</html>

取得頁面的程式碼:
記得要 using HtmlAgilityPack; 
參閱文章:IT閱讀C# HtmlAgilityPack @ 幽嵐飋翼

//引用的類別
using HtmlAgilityPack;
using System.Net;
using System.Xml.XPath;
using System.Data;

public partial class GetWebExchangeRatedata : System.Web.UI.Page
{   
    protected void Page_Load(object sender, EventArgs e)
    {
     
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
            GetChinaBankRate();
    }

    private void GetChinaBankRate()
    {
        try
        {
            HtmlWeb webClient = new HtmlWeb();
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
            int pg = 1;
            string date = DateTime.Today.ToString("yyyy-MM-dd");
            string url = string.Format("https://srh.bankofchina.com/search/whpj/search_cn.jsp?erectDate={0}&nothing={1}&pjname=%E7%BE%8E%E5%85%83&page={2}&head=head_620.js&bottom=bottom_591.js", date, date, pg);
            HtmlDocument doc = webClient.Load(url);
            HtmlDocument ratedoc = new HtmlDocument();
            ratedoc.LoadHtml(doc.DocumentNode.SelectSingleNode("//*[@class='BOC_main publish']").InnerHtml);
        
            if (ratedoc == null) return;

            DataTable dt = new DataTable();

            foreach (HtmlNode table in ratedoc.DocumentNode.SelectNodes("//table"))
            {               
                HtmlNodeCollection headers = ratedoc.DocumentNode.SelectNodes(@"//table/tr/th");
                foreach (HtmlNode header in headers)
                {
                    dt.Columns.Add(header.InnerText);
                    //寫入表單標題
                }

                for (int i = 1; i < table.SelectNodes("tr").Count; i++)
                {
                    string rowtr = string.Format("//table/tr[{0}]", i);
                    foreach (HtmlNode row in ratedoc.DocumentNode.SelectNodes(rowtr))
                    {
                        if (i == 1)
                        {
                            //datatable表單單頭,已經處理了..其實可以int = 2 開始for迴圈...
                        }
                        else
                        {
                            DataRow dataRow = dt.NewRow();
                            int dd = row.SelectNodes("td").Count;
                            for (int j = 0; j < row.SelectNodes("td").Count; j++)
                            {
                                var td = row.SelectNodes("td")[j].InnerText;
                                dataRow[j] = td;
                            }
                            dt.Rows.Add(dataRow);
                        }
                    }
                }

            }
            getRateAndTime(dt);
            GridView1.DataSource = dt;
            GridView1.DataBind();
        }
        catch (Exception ex)
        {
            // 繼續執行
        }
    }

#region 檢查時間點,取得特定時間點的匯率資料
 private string getRateAndTime(DataTable dt)
    {
        string str = "";
        string date1 = DateTime.Today.ToString("yyyy-MM-dd 09:30:00");
        string date2 = DateTime.Today.ToString("yyyy-MM-dd 09:31:00");
        string x = string.Format("发布时间 > #{0}# AND 发布时间 < #{1}#", date1, date2);
        DataRow[] result = dt.Select(x);

        foreach (DataRow row in result)
        {
            string rowdata = row["现汇卖出价"].ToString();
            string date = row["发布时间"].ToString();
            if (string.IsNullOrEmpty(rowdata))
            {
                Label1.Text = string.Empty;
            }
            else
            {
                string money = rowdata;
                string time = date;

                Label1.Text = string.Format("{0}  +  {1}", money, time);
            }
        }
        return str;
    }
#endregion
}

由於對Xpath不熟悉,所以當天在拆解來源頁面資料時,遇上瓶頸,光是<tr><td> 在 DocumentNode.SelectNodes 的拆解就弄得焦頭爛額,怎麼樣就是沒有辦法將頁面資料直接拆解寫入DataTable中。
回家沉澱一晚後,隔天上班就順順的直接寫出來......(當天真的鬼打牆....),還好順利解開。

紀錄一下,感覺以後還會有機會做這類型的運用。

水滴可成涓流,涓流可成湖泊大海。
汲取累積知識,將知識堆積成常識;將常識探究成學識;將學識簡化為知識;授人自省。