以前用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
//
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而已,想不通。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/111004.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...