(1)在上篇博客中向大家展示了,在国庆期间没出来看人海,于是宅在家弄了个景点热力图,回顾下图做出来的样子:
(2)这篇文章的接下来将和大家分享技术的实现,并很乐意分享相关的源码和大家交流。
1.前台部分,百度api的讲解,先参考下该demo
地图显示部分,主要是调用了BMapLib包下的类HeatMapOverlay,该类相关的设置在demo中可以参考,不过本图数据是需要从后台获得的,所以我在脚本中加入一个调用前台的方法,至于方法如何用,我在后面会将。
var data=window.data.getData()
2.后台部分
2.1 数据的获取,数据的准确性和完整性直接影响到热力图的显示,我这里抓取了 去哪儿网站--门票--搜索关键字 所有数据,这里的搜索关键字就是我要抓取的城市名字。
(1)在bing上搜索和下载(复制也行,反正不多)全国城市名字,将其保存为text文本格式,如我的:
在去哪儿的网站上通过搜索上面城市的名字后可以得到源码,在源码中可查找得到景点的个数、景点名字、景点地址、景点经纬度值、景点出售的门票数,这些字段是我们画热力图的数据。
(2)数据保存,我的数据保存在mysql中,当然你也可以用其他的数据库或文本都行(最好用数据库,便于数据的查询和管理),下载mysql客户端,安装过程就大家自行参考教程。下面我将数据表的设计部分,数据表的设计包括创建数据库-创建表-插入数据;
create database scene;
创建表scene:
create table scene(
id int(10) primary key not null auto_increment,
country varchar(20) not null,
name text not null,
various varchar(20),
locate text not null,
lng Double(15,12) not null,
lat Double(15,12) not null,
address text not null,
hots int(10) not null
);
注意lng经度坐标和lat维度坐标用Double类型,我用float类型时就发现float对精度问题,当数据长度不够时,保存下来的数据为近似值,如float(15,12)为字段类型,要存的数据为121.12,查看该值在数据表是为121.11232等,建议用Double类型
(3)现在就是将数据从网站上趴下来(注意做点代理什么的策略,我就是没注意,现在一直进不去),这里我的技术实现路线是:
spring-data + scala +Actor
上面的spirng-data用spring的api将数据连接至mysql写入数据表中,需要源码的留言哦
项目用scala语言实现,优点是处理数据会方便;
抓取数据不可避免的需要多线程,这里用AKKA的actor实现,很方便实现多线程。
我这里一个server类和client类,server类用于向client分配爬取数据任务、收集client数据、相mysql写数据;client作用是接收server的任务,将抓取的结果发送给server。
项目的结构如下:
(4)数据的前后台交互。
后台的数据交互我这里采用jxbrowser插件来实现,jxbrowser有利于多个窗口的显示,这里jxbroser还有强大的功能,能和前后台交互,之前在html中我插入了获取后台数据的方法的函数,现在来说下如何用。
通过调用broser实例的监听,可以知道前台是否有调用后台方法:
browser.addScriptContextListener(new ScriptContextAdapter() {
override def onScriptContextCreated(event: ScriptContextEvent): Unit = {
val window = event.getBrowser.executeJavaScriptAndReturnValue("window") //js前台执行window.MQMsgData.sendMQMsg(msgType,msgValue);
window.asObject.setProperty("data", new Data)
}
定义一个和window.data交互的类:
class Data{
def getData():JSONString={
val d=ScenicDaoImp.query.toArray.map(scene=>{
new HotData(scene.position.lng,scene.position.lat,scene.hots)
})
new JSONString(new Gson().toJson(d))
}
}
这样前台的window.data.getData就直接触发Data.getData()返回数据给前台了,注意数据的格式。
(5)终于写完了,如果还有不懂的地方就留言。明天打算在上海玩下算了,我去看下上海景点,陆家嘴附近的人永远都是还是这么多!