前面幾篇已經完成了前端3D疫情地球的實現和疫情數據的爬蟲,如何將這兩個連接起來,須要在這兩個程序之間搭建一個服務html
服務類型不少,這裏使用websocket實現前端
1 websocket服務端python
2 websocket客戶端mysql
這裏使用python實現一個簡易的websocket服務端,藉助python組件websockets便可實現git
新建一個server.py,作一個簡單鏈接驗證,代碼最後設定服務地址爲 localhost:9998 github
import asyncio import websockets import json from mysqlDataAccess import MysqlDataAccess import logging from datetime import datetime import time interval = 60 logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s', level=logging.INFO) logging.info('websocket服務啓動') # 檢測客戶端權限,用戶名密碼經過才能退出循環 async def check_permit(websocket): while True: recv_str = await websocket.recv() cred_dict = recv_str.split(":") if cred_dict[0] == "admin" and cred_dict[1] == "123456": logging.info('認證經過') return True else: content = {"code": 0, "msg": "authentication failed"} logging.info('認證失敗') await websocket.send(json.dumps(content)) # 接收客戶端消息並處理,這裏只是簡單把客戶端發來的返回回去 async def send(websocket): await send_data(websocket) while True: await send_data(websocket) time.sleep(interval) # 服務器端主邏輯 async def main_logic(websocket, path): await check_permit(websocket) # await recv_msg(websocket) await send(websocket) async def send_data(websocket): access = MysqlDataAccess() data = access.getData() logging.info('數據獲取完成') await websocket.send(json.dumps(data)) logging.info('信息發送中') start_server = websockets.serve(main_logic, 'localhost', 9998) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()
裏面調用了一個MysqlDataAccess類,這個用來定時的從mysql數據庫獲取數據,相關代碼以下,實現了MySQL的疫情數據的讀寫web
import pymysql MYSQL_HOST = 'localhost' MYSQL_DB = 'covid19' MYSQL_USER = 'root' MYSQL_PASSWORD = '123456' MYSQL_PORT = 3306 class MysqlDataAccess: def __init__(self,host = MYSQL_HOST,database=MYSQL_DB,user=MYSQL_USER,password=MYSQL_PASSWORD,port=MYSQL_PORT): try: self.db = pymysql.connect(host,user,password,database,charset='utf8',port=port) self.cursor = self.db.cursor(cursor=pymysql.cursors.DictCursor) except pymysql.MySQLError as e : print(e.args) def updateCountryPosition(self,name,lng,lat,type): sql_update = 'insert into dic_lnglat (name,lng,lat,type) values(%s,%s,%s,%s) on duplicate key update' sql_update += ' name= %s,lng=%s,lat=%s,type=%s' try: self.cursor.execute(sql_update,(name,lng,lat,type) * 2) self.db.commit() print(name) except pymysql.MySQLError as e: print(e.args) self.db.rollback() def getData(self): sql_query = 'SELECT a.name,b.lng,b.lat,IFNULL(a.new,0) as new,IFNULL(a.now,0) as now,IFNULL(a.total,0) as total,IFNULL(a.cure,0) as cure,IFNULL(a.death,0) as death from covid19 a inner join dic_lnglat b on a.`name`=b.`name`' try: self.cursor.execute(sql_query) return self.sql_fetch_json() except pymysql.MySQLError as e: print(e.args) def sql_fetch_json(self): keys = [] for column in self.cursor.description: keys.append(column[0]) key_number = len(keys) json_data = [] for row in self.cursor.fetchall(): item = dict() for q in range(key_number): item[keys[q]] = row[keys[q]] json_data.append(item) return json_data
這樣一個簡單的websocket服務就完成了sql
爲了啓動簡單,在windows環境下,新建一個socketServer.bat用來啓動服務數據庫
@echo off F: rem ִ開啓socker服務 cd F:\mygithub\VDDataServer\SocketServer python3 server.py TIMEOUT /T 10 exit
執行bat就能夠打開服務json
websocket的客戶端,VDEarth是基於js的前端可視化應用,這裏須要實現一個前端的websocket客戶端,這裏直接對以前的VDEarth前端組件進行改造
在VDEarth項目文件夾src文件夾下新增一個socket.js, 新增socket訪問類
import _ from 'lodash'; function reconnect() { console.log('從新鏈接'); } function open() { // Web Socket 已鏈接上,使用 send() 方法發送數據 this.ws.send(this.account + ':' + this.password); } // 接受數據執行回調方法 function receive(evt, callback) { var data = evt.data; if (_.isFunction(callback)) { callback(JSON.parse(data)); } } function close() { // 關閉 websocket console.log('鏈接已關閉...'); reconnect(); } function reload() { this.ws.send('reload'); } class socket { constructor(server, port, account, password) { this.account = account; this.password = password; this.server = server; this.port = port; } init(onmessage) { if ('WebSocket' in window) { try { this.uri = 'ws://' + this.server + ':' + this.port; this.ws = new WebSocket(this.uri); this.ws.onopen = () => { open.call(this); }; this.ws.onmessage = (evt) => { receive.call(this, evt, onmessage); }; this.ws.onclose = () => { close.call(this); }; window.onbeforeunload = () => { reload(); }; } catch (error) { console.log(error); } } else { // 瀏覽器不支持 WebSocket console.log('您的瀏覽器不支持 WebSocket!'); } } } export default socket;
修改VDEarth.js
數據的加載主要是用在了柱形圖和名稱標記那裏,因此修改那裏的代碼,即initObj方法,VDEarth類的options方法配置默認的socket連接,server = localhost,port = 9998,account = admin,password = 123456
// 建立模型 function initObj() { let self = this; let fontloader = new FontLoader(); // 建立地球模型組 this.baseGroup = new Group(); // 建立地球 this.radius = minSize(this.contentWidth, this.contentHeight) * 0.2; let globalMesh = new model().createGlobe(this.radius, this.textrue); this.baseGroup.add(globalMesh); // 建立星點 let stars = new model().createStars(); this.baseGroup.add(stars); // 建立鏈接 var mySocket = new socket( this.options.server, this.options.port, this.options.account, this.options.password ); mySocket.init(function (data) { // 建立一個標記組 self.markerGroup = new Group(); // 建立標記 var myMarkers = new marker(); // 柱形 myMarkers.addBoxMarkers(self.markerGroup, self.radius, data); // 加載字體 if (self.font) { myMarkers.addNameMarkers(self.markerGroup, self.radius, data, self.font); } else { fontloader.load('./fonts/SimHei_Regular.json', function (font) { self.font = font; myMarkers.addNameMarkers( self.markerGroup, self.radius, data, self.font ); }); } self.baseGroup.add(self.markerGroup); }); this.scene.add(this.baseGroup); }
至此定時數據推送和VDEarth的展現更新就完成了
打開爬蟲服務,打開websokcet服務,打開瀏覽器就輸入VDEarth 的web容器的地址就能夠了
相關連接
從0開始疫情3D地球 - 3D疫情地球VDEarth - 1- 引言
從0開始疫情3D地球 - 3D疫情地球VDEarth - 2 - 前端代碼構建
從0開始疫情3D地球 - 3D疫情地球VDEarth - 3 - 3D地球組件實現(1)
從0開始疫情3D地球 - 3D疫情地球VDEarth - 4 - 3D地球組件實現(2)