網頁爬蟲、使用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}¬hing={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中。
回家沉澱一晚後,隔天上班就順順的直接寫出來......(當天真的鬼打牆....),還好順利解開。
紀錄一下,感覺以後還會有機會做這類型的運用。
水滴可成涓流,涓流可成湖泊大海。
汲取累積知識,將知識堆積成常識;將常識探究成學識;將學識簡化為知識;授人自省。