利用Linux虚拟主机打造自己的网络信息传送门

最近完成了一个日本公司的库存管理系统,开发费很准时的汇到了我的中行账户里。收日元是件很有成就感的事,那一堆零,看着就爽……不过这都是浮云啊,不换成人民钱怎么给我家包子买奶粉啊。最近日本受灾,日元汇率波动挺大,听某些专家讲,因为要筹集重建资金,日元总体还是要涨的。所以我给自己定了一个门槛,打算等汇率过了8.09才去兑换。可是要为了这个每天都要想着上网刷新中行的外汇牌价页面,感觉很麻烦,错失良机的可能性极大。所以就想做一个定时抓取网上汇率信息的web service,时时刻刻帮我盯着,一旦超过阙值,就用短信通知自己。感觉这个服务就象Portal–传送门,网上信息从一头儿扎进去,转啊转的,从另一头儿的个人短信端(email也行)就钻出来了。虽然我玩Portal游戏玩到头晕要吐,到第17关再也坚持不下去认输放弃了,但是自己做这个服务还是没什么问题的,花了周末一天时间搞定,也算是个实用的weekend project,记录下来给有类似需求的人做个参考。

事前准备

  1. 要获取的信息是互联网上公开的,信息展现页面格式基本固定无变化,以便机器按照一定的规律定时抓取;
  2. 有管理员权限的Linux虚拟主机服务,除了能够放PHP一类的活动页面程序外,最重要的是要有SSH登录,cron job和send mail功能;
  3. 如果要通过手机短信收取通知信息,需要有和自己的手机号码绑定的139.com信箱一个(联通电信应该也有类似的服务)。

制作过程

  1. 找到你要定时监视的网上信息源,记录下网址,然后看网页源代码,找到自己需要的部分,分析确定如何把这个数据准确地从其它信息中分离抓取出来。我就以中行外汇牌价页面信息为例说明:
    查看源代码
    我要抓的是日元现汇买入价,看上面的源代码可以发现,这个数字就在第一次出现日元两个字后面的第二行,去掉两头的<td bgcolor=”#FFFFFF”>和</td>以及一堆空格就行了;
  2. 用SSH工具登录到自己的虚拟主机上,建立一个有执行权限的脚本文件scraper1.sh,代码如下:

    ##!/bin/sh
    dataSourceUrl="http://www.boc.cn/sourcedb/whpj/"  
    dataProcessUrl="http://yourhosting.com/service1.php"  
    exchangeRateFigure=$(wget -q -O- $dataSourceUrl --header 'Cache-control:no-cache' | iconv -f utf-8 -t gbk | sed -n '/日元/{n;s///;s///;s/ //g;p;}')  
    exchangeRateDate=$(wget -q -O- $dataSourceUrl --header 'Cache-control:no-cache' | iconv -f utf-8 -t gbk | sed -n '/日元/{n;n;n;n;n;n;s///;s///;s/ //g;p;}')  
    exchangeRateTime=$(wget -q -O- $dataSourceUrl --header 'Cache-control:no-cache' | iconv -f utf-8 -t gbk | sed -n '/日元/{n;n;n;n;n;n;n;s///;s///;s///;s/ //g;s/:/%3A/g;p;}')  
    dataProcessUrl=$dataProcessUrl"?sid=1&dv1="$exchangeRateFigure"&dv2="$exchangeRateDate"&dv3="$exchangeRateTime wget -q -O- dataProcessUrl

    简要说明一下:第5行:首先是访问信息源网址获取网页,将网页从UTF-8编码转换为GBK编码,找到日元出现后的下一行信息,将,和所有空格信息去掉后,获得的数据存入变量中。

  3. 登录你的虚拟主机控制面板,在cron job中,按照你需要的定时间隔,执行上面的脚本,我的设定是:*/15 * * * * ~/public_html/prj/scraper1.sh,也就是每隔15分钟执行该路径下的scraper1.sh去抓取数据;

  4. 按照前面代码中建立的页面处理地址,在虚拟主机中建立相应的service1.php页面,同时建立一个有写入权限的service1.log文件,以便存储抓取来的数据。数据处理页面我用的是PHP,代码如下:

    <?php
    $handle=fopen("service1.log","r");
    $dataLine=fgets($handle); fclose($handle);
    $logData=explode(",", $dataLine);
    $alertThreshold=8.09;//触发短信通知的阙值
    $exchangeRateFigure=$_GET['dv1'];
    $exchangeRateDate=$_GET['dv2'];
    $exchangeRateTime=$_GET['dv3'];
    if($logData[0]!=$exchangeRateFigure) {  
    	$handle=fopen('service1.log','w');
    	fwrite($handle,$exchangeRateFigure.','.$exchangeRateDate.','.$exchangeRateTime.','.$logData[3]);
    	fclose($handle);
    	if($exchangeRateFigure>=$alertThreshold && $exchangeRateDate!=$logData[3]){
    		$headers='From: aaa'.'rn'.'Reply-To: aaa@yourhosting.com'.'rn'.'X-Mailer: PHP/'.phpversion();//发件人和回复地址可以随便写
    		$to='13600000000@139.com';//你的139信箱地址
    		$subject='100 JPY now is '.$exchangeRateFigure.' CNY!';
    		$body='Date: '.$exchangeRateDate.', Time: '.$exchangeRateTime.', Figure: '.$exchangeRateFigure;
    		mail($to, $subject, $body,$headers);
    		$handle=fopen('service1.log','w');
    		fwrite($handle,$exchangeRateFigure.','.$exchangeRateDate.','.$exchangeRateTime.','.$exchangeRateDate);
    		fclose($handle);
    	}
    }

    简要说明:这个页面的功能就是首先从service1.log文件中读取以往记录的数据,然后和新收到的数据比较,如果汇率数据不同,就将新信息和上一次短信通知日期的信息覆盖记录到service1.log文件中,下一步判断如果汇率达到阙值,且当天没有发送过短信通知,就给你手机绑定的139.com信箱地址发一封email,将汇率信息包含在信中,然后将新数据和当天日期覆盖记录到service1.log文件中;

  5. 用浏览器登录你的139.com信箱,开启邮件到达短信通知功能(只要不是彩信,其它几种形式都是免费的),这样就完成了!

最后还想说明的是:1)有send mail, ssh登录和cron job功能的Linux虚拟主机在国内不是每家都有,但是在国外算是基本配置,价格比国内还便宜(基本上是五、六美元到十几美元/月),加上有SSH功能的虚拟主机还可以用来架设SSH TUNNLING服务给自己及几个至亲好友做翻墙用,这么算下来可真是鱼翅卖白菜价了,超值啊。2)这个传送门除了抓抓汇率信息,还可以有很多用处,我现在能想到的有:监视自己的交通一卡通余额,低于十元就通知赶紧充值;每天早上抓天气预报,有极端情况(雨雪降温酷热等)就通知一下;家庭安全监视……请大家集思广益吧!