作業概況
這個作業屬於哪個課程 | 班級的鏈接 |
---|---|
這個作業要求在哪里 | 作業要求的鏈接 |
結對學號 | 221701104,221701116 |
這個作業的目標 | 完成疫情webapp的基礎功能包括: 顯示全國地圖數據,點擊省份可以顯示具體的變化趨勢 |
作業正文 | 作業正文 |
其他參考文獻 | ... |
giithub地址
成品展示
作業鏈接(服務器帶寬很小,渲染和加載需要時間)
接口可能會因為不穩定導致獲取不到數據,可將index.js中獲取接口的.ajax的url更換為https://lab.ahusmart.com/nCoV/api/area進行嘗試。(2020/3/19)
以上鏈接可能由於API的不穩定而失效,如果失效,請使用下面的鏈接(2020/3/22)
作業鏈接
此作業鏈接對應github中release的1.0.1版本
一、主頁
1、在頁面的左上角有個“首頁”的標志,點擊能夠返回主頁(也就是下方圖片顯示的頁面)
2、點擊全國趨勢查看全國數據以及全國新增趨勢圖
3、時間戳會根據當天時間實時更新,地圖采用API接口,也會實時更新數據
4、省份區塊的顏色按照累計確診人數的多少決定顏色的深淺
5、將鼠標懸浮在省份上,該省份區塊會高亮顯示並顯示累計確診人數(如下圖)
6、點擊該省份區塊,會跳轉至該省份數據顯示以及新增趨勢圖的頁面
7、由於全國數據部分(上半部分,非地圖數據)是將爬取的數據轉化成json文件讀取,所以暫時未能實現實時更新,文件最新日期為2020-03-12
8、可以直接查看數據
二、全國趨勢
1、在頁面的左上角有個“首頁”的標志,下方還有個返回標志,點擊兩處都能夠返回主頁
2、點擊全國趨勢查看全國數據以及全國新增趨勢圖(也就是當前頁面)
3、點擊日期選擇框能夠選擇日期,可選最早日期為2020-01-25,可選最晚日期為2020-03-12(因為數據部分是將爬取的數據轉化成json文件讀取,所以暫時未能實現實時更新,文件最新日期為2020-03-12)
4、選擇日期后點擊確認,下方的數據表和新增趨勢圖就會變換至選擇日期的數據情況
5、點擊圖例,可選擇要顯示的新增類型
6、懸浮在趨勢圖上,可查看某天各個類型的新增人數(已關閉的趨勢圖不會顯示)
7、這里只顯示新增疑似和新增治愈(點擊新增感染和新增死亡的圖例,將這兩幅新增趨勢圖關閉)
8、點擊日期選擇框,會發現可選日期和不可選日期的底色上有差異
9、選擇好日期點擊確認,下方數據表和趨勢圖已變化。
三、省份趨勢
此處效果與全國趨勢圖大同小異,不同點為省份位置的位置會根據所選省份發生變化
結對過程展示
剛剛拿到作業覺得這次作業的問題並不多,因為上次原型制作的時候就使用了Echarts,這次對我們來說的主要難度就是數據的獲取,數據的處理和數據的渲染。
0. 前期工作
創建倉庫和dev,.ignore和ReadMe等部分。溝通GitHub的使用方法。新建代碼規范。
討論GitHub的使用細節
1. 分工
一個人將原型的樣子用前端CSS代碼復現出來,另一個人去尋找相關網頁爬取下來各省數據和全國歷史數據。
2. 數據爬下來后進行數據處理,對Echarts進行渲染
3. 文件合並,實現跳轉和整體邏輯
設計實現過程
設計過程
-
網頁設計
- 網頁架構形成
- CSS處理
- Echarts導入
-
數據爬取
-
功能實現
- 將功能分為:地圖展示和趨勢圖展示。兩個模塊分開設計
- 地圖展示需要獲取全國各地的最新數據,通過爬蟲獲取數據之后返回到頁面,頁面挑選參數,通過js代碼獲取每個地區的數據,然后渲染到Echarts上
- 趨勢圖展示
- 地圖展示部分和趨勢圖展示的鏈接和跳轉
- 通過Echarts的onclick函數獲取到選取的地圖塊位置,點擊后跳轉傳遞url,附帶參數name,通過name傳遞被點擊的地區。
- 趨勢圖展示接收到傳過來的地區,讀取對應的數據文件,進行處理,得出時間對應的數據。
- 數據渲染到Echarts圖標上,允許對圖例操作進而進行篩選。
功能結構圖
主要代碼
python部分
爬取數據的代碼類似如下,其他爬取函數類似不再贅述:
def get_tecent_china_data():
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other'
r = requests.get(url)
res = json.loads(r.text)
data_all = json.loads(res['data'])
history = {} # 歷史數據
for i in data_all["chinaDayList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds,"%Y.%m.%d")
ds = time.strftime("%Y-%m-%d",tup)
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds] = {"confirm":confirm, "suspect":suspect, "heal":heal, "dead":dead}
for i in data_all["chinaDayAddList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds,"%Y.%m.%d")
ds = time.strftime("%Y-%m-%d",tup)
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds].update({"confirm_add":confirm, "suspect_add":suspect, "heal_add":heal, "dead_add":dead})
return history
找到騰訊的疫情地圖,通過開發者模式的網頁模式獲取騰訊前端請求的json頁面,也即url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other'
,然后通過requests組件發出讀取請求讀取到json文件,隨后進行爬取。
def insert_history():
cursor = None
conn = None
try:
dic = get_tecent_china_data()
print(f"{time.asctime()}開始插入歷史數據")
conn, cursor = get_conn()
sql = "insert into history values(%s, %s, %s, %s, %s, %s, %s, %s, %s)"
for k, v in dic.items():
cursor.execute(sql,[k, v.get("confirm"),v.get("confirm_add"),v.get("suspect")
, v.get("suspect_add"), v.get("heal"), v.get("heal_add")
, v.get("dead"),v.get("dead_add")])
conn.commit()
print(f"{time.asctime()}插入歷史數據完畢")
except:
traceback.print_exc()
finally:
close_conn(conn, cursor)
用python連接MySql數據庫,實現數據的本地化儲存。
html部分
設置日期選擇框,可選最早日期為2020-01-25,最晚為2020-03-12
<input type="date" required min="2020-01-25" max="2020-03-12" id="date">
<input type="button" id="confirm" value="確認">
設置好需要改變數據的位置,便於之后編寫js文件的改變html內容
<!--ip_num:累計確診-->
<div class="num" id="ip_num"></div>
<!--sp_num:現有疑似-->
<div class="num" id="sp_num"></div>
<!--cure_num:累計治愈-->
<div class="num" id="cure_num"></div>
<!--dead_num:累計死亡-->
<div class="num" id="dead_num"></div>
<!--ip_incrs:(較昨日)新增確診-->
<div class="increase" id="ip_incrs"></div>
<!--sp_incrs:(較昨日)新增疑似-->
<div class="increase" id="sp_incrs"></div>
<!--cure_incrs:(較昨日)新增治愈-->
<div class="increase" id="cure_incrs"></div>
<!--dead_incrs:(較昨日)新增死亡-->
<div class="increase" id="dead_incrs"></div>
設置繪制圖表位置,引入相應的js文件
<!--趨勢圖-->
<div id="province"></div>
<script src="../js/province.js"></script>
javaScript部分
地圖渲染
function fuc() {
var list
$.ajax({
url:"https://lab.isaaclin.cn/nCoV/api/area",
async:false,
type:"get",
data:{
"latest":"1"
},
dataType:"json",
success:function (data) {
list = data["results"];
},
error:function () {
alert("讀取失敗")
}
})
return list
}
利用ajax調用API獲取各地區的數據列表,返回一個json數據類型。
然后簡單地通過js函數實現數據返回
function getNum (province) {
var l = fuc()
for (var i in l) {
if (l[i]["provinceName"] == province) {
return l[i]["confirmedCount"]
}
}
}
數據獲取
1、根據點擊省份區塊傳入的參數,選擇json文件
2、使用javascript原生XMLHttpRequest的方法來讀取json
window.onload = function () { //加載頁面時
var string = location.search; //獲取url中"?"符后的字串
var province = decodeURI(string).replace("?","");
var url;
switch (province) { //根據得到的字符串,選擇對應的json文件
case "安徽":
url = "../json/areaAnHui.json";
break;
...
}
var request = new XMLHttpRequest(); //發送http請求
request.open("get", url);
request.send(null);
request.onload = function () {
if (request.status == 200) { //如果成功
var json = JSON.parse(request.responseText); //解析json字符串
...
之后進行相應讀取和保存數據的操作
}
}
繪制圖表
}
數據處理
1、時間格式處理(json文件中遇到時間格式為1545299299910,需要轉化為yyyy-mm-dd的格式)
var date = new Date(json.results[0].updateTime);
var month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1;
var currentDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var string = date.getFullYear() + "-" + month + "-" + currentDate; //string就為所需格式
2、某天數據可能不止一條,所以某天時間可能重復出現,采用判斷,將已記錄的時間數據忽略(該方法限於時間按順序出現)
if(temp != dateList[j-1]){ //如果該時間已經記錄過
dateList[j] = date.getFullYear() + "-" + month + "-" + currentDate;
ip_num[j] = json.results[i].confirmedCount;
sp_num[j] = json.results[i].suspectedCount;
cure_num[j] = json.results[i].curedCount;
dead_num[j] = json.results[i].deadCount;
j++;
} else {
ip_num[j-1] = json.results[i].confirmedCount;
sp_num[j-1] = json.results[i].suspectedCount;
cure_num[j-1] = json.results[i].curedCount;
dead_num[j-1] = json.results[i].deadCount;
}
3、新增人數的獲取:由於爬取的數據並非包含所有的數據,例如各類型新增數據;使用當天該類型人數減前一天該類型人數得到新增數據。
var ip_incrs = new Array(); //(較昨日)新增確診
ip_incrs[0] = 0;
for(var i = 1; i < ip_num.length; i++){
ip_incrs[i] = ip_num[i] - ip_num[i-1]; //今日-昨日
}
4、根據所選日期處理時間數組,再通過新的時間數組長度限制其他數組
var dateList1 = new Array();
for(i = 0; i < dateList.length; i++){
if(date_limit < dateList[i]) //如果該日期超過選擇日期
break;
dateList1[i] = dateList[i];
}
var ip_incrs = new Array(); //(較昨日)新增確診
ip_incrs[0] = 0;
for(var i = 1; i < dateList1.length; i++){ //使用限制時間下的時間數組長度
ip_incrs[i] = ip_num[i] - ip_num[i-1];
}
心路歷程、收獲和對隊友的評價
221701104 潘晨宇
本次的作業在一開始估計的時候以為應該會比較簡單,畢竟只是數據的爬取和處理渲染,應該不會太難。但是實際操作的時候還是問題多多。我自己負責數據的爬取和固定化,先要去摸索一個新的python語言的語法和方法,然后去尋找各個網頁找到自己需求的數據,最后固定化下來。這個過程其實並不像我想象的簡單,相反還花了很多的時間,后來在渲染全國地圖的時候調用爬蟲返回的數據也沒有很快,還需要讀取覺得水平有待提高。
對我的隊友221701116 陳炎:我覺得他是一個很棒的實干者,說做就做,效率也很高,當時處理數據的時候把json包傳過去后他很快就着手進行處理,在寫代碼上毫不含糊。他寫代碼也十分可靠,在寫代碼的時候,趨勢圖的數據處理完全由他自己進行函數處理,是個很可靠的隊友。
221701116 陳炎
在本次作業發布當天就去瀏覽了作業內容,大致瀏覽完,便發現了很多新知識、新技術,當時便覺得有些不知所措。在之后的實現中,先采取從最必要的開始,也就是GitHub的使用,建立結對倉庫,這樣才能保證代碼寫完后能夠commit,並與隊友共享使用。之后因為爬取數據需要python但並沒有接觸過,也就產生了焦慮心理。在隊友接下爬取數據的重任后,開始按部就班設計頁面樣式,學習讀取數據。在學習讀取數據過程中,也出現了許多問題。之后不斷查找資料,不斷嘗試,雖然每次失敗后會煩躁,但還是會再次搜索出現的問題,瀏覽一個個解決辦法。在本次作業的收獲里,最主要的並非是技術,而是那種學習完成項目中不斷嘗試所磨練的耐心。通過本次作業還發覺自己在新技術面前的學習力還不夠強大,不能夠以更好地心態去面對,這些還需要再做提升。
對我的隊友221701104 潘晨宇:他是一個學習力很強、思維靈活、體貼的隊友,能夠很好地學習新技術,並應用到項目中來;在方法選擇上,能采取更高效的方式;在分工上也很照顧隊友,主動挑起更重的擔子。他像是將管理和工作的結合體,不僅能更好地發揮團隊合作能力,也能夠將自己項目的部分完成得井井有條。
版本更新
1.0.1版本解決了之前的API失效的問題。但代碼尚有不完全的地方,請助教幫忙指正如下:
js代碼
function fuc() {
var list
$.ajax({
url:"https://lab.ahusmart.com/nCoV/api/area",
async:false,
type:"get",
data:{
"latest":"1"
},
dataType:"json",
success:function (data) {
list = data["results"]
console.log(list);
},
error:function () {
alert("讀取失敗")
}
})
return list
}
function f() {
dataList = fuc().filter(r => {
return r.country == "中國" && r.provinceName !="待明確地區"
}).map(r => {
return {
name:r.provinceShortName,
value:r.confirmedCount
}
})
}
以上代碼用以處理API返回的數據,但是每次讀取頁面都需要重復執行function f()
導致頁面的渲染很慢。希望助教能提出建議改進。
現有想法兩點:1.將API的處理放到服務器上,直接返回處理好的數據。2.將處理好的數據放到本地localstorage或cookie中,這樣只需要第一次讀取,之后的讀取都不會很慢。
以上希望助教能予以思路上的幫助。