大數據可視化-繪製景點熱力圖

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/humanity11/article/details/78151119
(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)終於寫完了,如果還有不懂的地方就留言。明天打算在上海玩下算了,我去看下上海景點,陸家嘴附近的人永遠都是還是這麼多!






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章