以前用C#实现了从QQ天气网页提取天气信息显示,最近了解Flex,随便测试了一下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 }
用mxmlc命令编译之后,运行效果如下:
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而已,想不通。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111004.html原文链接:https://javaforall.cn