Flex实现QQ网页提取天气信息
1、预备知识
Flex是Adobe提供的基于Flash环境的RIA展现技术,主要采用MXML+Action Script来编写程序、界面,然后通过编译器编译成flash格式的SWF文件发布到网站上。
实现该功能需要安装Flex SDK,可以从Adobe网站上面下载,或者安装Flex Builder plugin+Eclipse来开发。
同时需要具备简单的正则表达式知识。
2、界面布局、代码实现
文件:QQWeather.mxml
<?xml version="1.0" encoding="utf-8"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="213" height="234" creationComplete="initApp()" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#F6FBFC, #3FEEDC]"> <mx:Style> .myfont{font-size:12pt;font-family:'宋体';} </mx:Style> <mx:Script source="QQWeather.as"></mx:Script> <mx:Label x="10" y="53" text="选择城市:" styleName="myfont"/> <mx:ComboBox id="cmbCity" x="66" y="49" width="133" rowCount="6" change="changeHandler(event);" styleName="myfont"></mx:ComboBox> <mx:Image x="10" y="10" source="@Embed('../title.gif')" width="189" /> <mx:Image x="10" y="106" source="@Embed('../tem1.png')" width="57" height="13"/> <mx:Image x="10" y="132" source="@Embed('../tem2.png')" width="57" height="13"/> <mx:Image x="10" y="178" source="@Embed('../tem3.png')" width="57" height="13"/> <mx:Image x="10" y="154" source="@Embed('../tem5.png')" width="57" height="13"/> <mx:Label x="75" y="103.5" text="" width="110" styleName="myfont" id="t1"/> <mx:Label x="75" y="129.5" text="" width="110" styleName="myfont" id="t2"/> <mx:Label x="75" y="151.5" text="" width="110" styleName="myfont" id="t3"/> <mx:Label x="75" y="175.5" text="" width="110" styleName="myfont" id="t4"/> <mx:Label x="34" y="202" text="Label" width="169" styleName="myfont" textAlign="right" id="lbToday"/> <mx:Label x="10" y="80" width="193" id="t0" styleName="myfont" fontWeight="normal"/> </mx:Application>
?
?
后台脚本:QQWeather.as
?
1 // ActionScript file 2 import flash.events.Event; 3 import flash.events.SecurityErrorEvent; 4 5 import mx.collections.ArrayCollection; 6 import mx.controls.Alert; 7 import mx.utils.Base64Encoder; 8 9 private var loader:URLStream;10 private var htmldata:String;11 private var ifloaded:Boolean=false;12 private var dataUrl:String="http://weather.qq.com/inc/ss*.htm";13 14 public function initApp():void{ 15 var t:Date=new Date();16 lbToday.text=t.fullYear+"-"+(t.month+1)+"-"+t.date+" "+t.hours+":"+t.minutes+":"+t.seconds;17 loadUrl("125",parseCityInfo);18 }19 private function loadUrl(cityno:String,callback:Function):void{20 loader= new URLStream();21 loader.addEventListener(Event.COMPLETE, callback);22 loader.addEventListener("securityError",onSecurityError );23 var addr:String=dataUrl.replace(/\*/,cityno);24 trace("Loading",addr);25 var request:URLRequest = new URLRequest(addr);26 //var enc:Base64Encoder=new Base64Encoder();27 //enc.encodeUTFBytes(addr);28 //var request:URLRequest = new URLRequest("http://localhost/httpproxy/webservlet?data="+enc.toString());29 try {30 loader.load(request);31 } catch (error:Error) {32 Alert.show("不能连接服务器:"+addr,"Tips");33 }34 }35 private function onSecurityError(event:SecurityErrorEvent):void{36 Alert.show("安全错误:"+event.text,"Tips");37 }38 private function parseCityInfo(event:Event):void {39 var sm:URLStream=event.target as URLStream;40 htmldata= sm.readMultiByte(sm.bytesAvailable, "gb2312"); 41 trace("completeHandler: " + htmldata );42 if(!ifloaded){43 var pattern:RegExp =new RegExp("value="(\\d{1,3})">([^<]*)</option>","g");44 var result:Object = pattern.exec(htmldata);45 var data:ArrayCollection = new ArrayCollection();46 var item:Object;47 while (result != null) {48 trace(result[1],result[2]);49 item=new Object();50 item.label=result[2];51 item.data=result[1];52 data.addItem(item);53 result = pattern.exec(htmldata);54 }55 cmbCity.dataProvider=data;56 ifloaded=true;57 }58 parseWeather();59 }60 private function parseWeather():void{61 //分析天气信息62 var item:Object=cmbCity.selectedItem;63 var pattern:RegExp =new RegExp("align="center">([^<]*)</td>","g");64 var result:Object = pattern.exec(htmldata);65 var data:Array=new Array();66 while (result != null) {67 data.push(trimString(result[1]));68 trace(result[1]);69 result = pattern.exec(htmldata);70 }71 t0.text=item.label+": "+data[0];72 t1.text=data[1];73 t2.text=data[2];74 t3.text=data[3];75 t4.text=data[4];76 }77 private function changeHandler(event:Event):void{78 var item:Object=ComboBox(event.target).selectedItem;79 trace(item.data);80 loadUrl(item.data,parseCityInfo);81 }82 private function trimString(s:String):String{83 return s.replace(/(^\s*)|(\s*$)/g, "");84 }
?
?
?
3、注意事项
根据flash的sandbox安全模型要求,A域名下的flash文件只能从A域名中获取服务端数据,如果需要从B域名中提取数据,需要B域名配置一个crossdomain.xml的文件,允许A从B
下载数据,但是我们不可能有这样的公关能力要求腾讯在http://weather.qq.com/下面放一个xml文件,允许其他网站访问,因此只能另辟蹊径:
方案1:A域名下自己实现一个代理,从B域名网页下载数据返回,这样就回避了sandbox的安全性错误,Line 26-28注释的代码就是我用java Servlet实现的一个代理。
方案2:建立代理服务器,例如squid或者Apache代理
方案3:采用adobe提供的开源软件bladeDS,该软件采用J2EE War方式发布,可以提供RPC、HTTP Proxy的代理功能
方案4:采用Adobe的企业级解决方案Adobe LiveCycle ES ,这个东西试用版就2.5G,真是庞然大物,受不了了,没见过这样的软件,一个Oracle数据库也就几百M而已,想不通。