[转载]C#基于HttpHelper的赶集抓票工具

[转载][C#]基于HttpHelper的赶集抓票工具 – 二杠 – 博客园.

每到年关,火车票总是一票难求,去年差点没买到票回家,看到赶集、58等上有转让票,大 喜,遂掏出手机呼叫之,可结果都是已转让。想想原因皆是看到的不及时,被别人捷足先登了。哥们是干什么的,居然从我嘴里抢食,越想越气,便做一工具,实时 在赶集上监控着,有新出售票就提醒,几天下来,一张D字头的到手。。。

闲扯了几句,下面进入正题。

开发这一工具大概思路就是从网页上获取HTML,然后用正则匹配之,匹配出有新数据数据时加入到网格中显示,另外不可能实时盯着这个工具看,必须在 有新信息时有提醒,于是我便加了一个声音提醒,一小时内的新信息都加声音提醒。这里遇到两个问题,一是如何从网页上抓取HTML,二是正则匹配问题。关于 抓取HTML,本人前一篇文章中已有介绍,见http://www.cnblogs.com/vanjoge/archive/2011/11/18/2253937.html,剩下的问题就是正则了,我们以赶集的T110次车为例来找到对应正则,首先打开赶集的T110次车的连接http://sh.ganji.com/piao/cc_T110/,图中红框部分就是我们需要抓取的数据

查看源文件,找到对应的HTML代码,如图:

图中选中部分则是单个车票信息,

<DL class=list_piao><DT><A href=”/piao/11111809_2887746.htm” target=_blank>[转让] T110 上海-北京 硬卧 2张 发车日期:11-18</A> </DT>
<DD class=list_piao_time>11月18日 </DD>
<DD class=list_piao_mj><A href=”http://www.ganji.com/lieche/cc_T110/” target=_blank>T110</A> </DD>
<DD class=list_piao_time>4小时前 </DD></DL>

下面祭出我们的正则神器:RegexTester,将HTML填入Source中,然后再一点一点的拼出正则,如图:

正则表达式即是:

<dl class=list_piao>\s*<dt><a href=([^]+) target=_blank>([^<]+)</a></dt>\s*<dd class=list_piao_time>([^<]+)</dd>\s*<dd class=list_piao_mj><a href=([^]+) target=_blank>([^<]+)</a></dd>\s*<dd class=list_piao_time>([^<]+)</dd>\s*</dl>

接下来便是设计界面,我就不在详述了,见图吧:

抓取逻辑:

1.抓取http://sh.ganji.com/piao/cc_T110/页面的HTML信息;

private void GetHtml()
{
string str = http.GetHTML(txtUrl.Text, */*, Encoding.UTF8, 20480);
this.Invoke(new invokeDelegate(Update), str);
}

2.用正则匹配HTML信息;

void Update(string str)
{
lblUpdateTime.Text = 更新时间: + DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss);
string pn = <dl class=\”list_piao\”>\\s*<dt><a href=\”([^\”]+)\” target=\”_blank\”>([^<]+)</a></dt>\\s*<dd class=\”list_piao_time\”>([^<]+)</dd>\\s*<dd class=\”list_piao_mj\”><a href=\”([^\”]+)\” target=\”_blank\”>([^<]+)</a></dd>\\s*<dd class=\”list_piao_time\”>([^<]+)</dd>\\s*</dl>;
Regex reg = new Regex(pn);
MatchCollection mths = reg.Matches(str);
foreach (Match item in mths)
{
Add(item.Groups[1].Value,
item.Groups[2].Value,
item.Groups[3].Value,
item.Groups[4].Value,
item.Groups[5].Value,
item.Groups[6].Value);
}
gridView1.BestFitColumns();
}

3.将新信息加入到网格中并声音提醒;

private void Add(string Url, string Text, string StartDate, string LUrl, string Vcc, string Time)
{
DataSet1.DTRow drow = GetDrow(dataSet11.DT, Url);//因为URL是唯一,因此根据URL获取是否已存在此火车票信息
int itemp = 0;
DateTime dt;
if (Int32.TryParse(Time.Replace(分前“”), out itemp))
{
}
else if (Int32.TryParse(Time.Replace(小时前“”), out itemp))
{
itemp = itemp * 60;
}
else if (DateTime.TryParse(strYear + Time, out dt))
{
itemp = Convert.ToInt32((DateTime.Now – dt).TotalMinutes);
}
if (drow == null)//不存在时追加
{
if (itemp < 60)
{
if (chkAuto.Checked)
{
OpenNewUrl(Text, strHost + Url, true);
}
PlaySoundSync();
}
dataSet11.DT.AddDTRow(Url, Text, StartDate, LUrl, Vcc, Time, itemp);
}
else//存在时更新间隔时间
{
drow.Time = Time;
drow.Ticks = itemp;
}
}

DataSet1.DTRow GetDrow(DataSet1.DTDataTable dt,string Url)
{
foreach (DataSet1.DTRow drow in dt)
{
if (drow.Url==Url)
{
return drow;
}
}

return null;
}

由于我们这个任务是需要定时的执行,因此要用到timer或Thread,这里我选择了用Thread,是为了防止在读取数据的过程中出现假死的情况,因此完整逻辑应该是:

1.开启任务

private void btnStart_Click(object sender, EventArgs e)
{
strYear = DateTime.Now.Year.ToString() + ;
if (chkUseProxy.Checked)
{
this.http.Proxy = new WebProxy();
try
{
this.http.Proxy.Address = new Uri(string.Format(http://{0}:{1}this.txtProxyServer.Text, this.spinProxyPort.Text));
if ((this.txtProxyUsername.Text.Length > 0) && (this.txtProxyPassword.Text.Length > 0))
{
this.http.Proxy.Credentials = new NetworkCredential(this.txtProxyUsername.Text, this.txtProxyPassword.Text);
}
}
catch
{
MessageBox.Show(代理设置出错,请检查代理设置!错误, MessageBoxButtons.OK, MessageBoxIcon.Error);
this.http.Proxy = null;
return;
}
}
else
{
this.http.Proxy = null;
}

IsRun = !IsRun;
if (IsRun)
{
Uri uri = new Uri(txtUrl.Text);
strHost = uri.Scheme + :// + uri.Host;
btnStart.Text = 停止监控;
txtUrl.Enabled = false;
System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
th.IsBackground = true;
th.Start();
}
else
{
btnStart.Text = 开始监控;
txtUrl.Enabled = true;
}
}

2.执行抓取逻辑

void Run()
{
while (IsRun)
{
GetHtml();
System.Threading.Thread.Sleep(5000);
}
}

最终执行效果:

附上源码:源码,不带DEV控件

由于此工具用了DEV10.1.4.0控件,因此没有此控件的童鞋需要下载DEV控件的DLL:本工具用到的DEV DLL

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏