結對第二次作業——某次疫情統計可視化的實現


這個作業屬於哪個課程 <班級的鏈接>
這個作業要求在哪里 https://edu.cnblogs.com/campus/fzu/2020SpringW/homework/10456
這個作業的目標 完成疫情統計可視化,並學習GitHub使用
結對學號 021700915、091700403
作業正文 https://www.cnblogs.com/lxbxyz/p/12489202.html
其他參考文獻 node.js教程GitHub使用教程JavaScript教程

程序GitHub倉庫地址為:https://github.com/ideaflyit/InfectStatisticWeb

一、成品展示

1.概述

疫情統計系統主要分為兩個頁面,分別為全國頁面和分省頁面。全國頁面主要包含全國疫情數據、全國疫情統計圖、全國確診總量趨勢圖、全國確診增量趨勢圖等。分省頁面主要包含各省疫情數據、各省確診總量趨勢圖、各省確診增量圖、省內各市確診,治愈,死亡人數的詳細數據以及實時疫情新聞等。

2.全國頁面

全國頁面主要包含全國疫情數據、全國疫情統計圖、全國確診總量趨勢圖、全國確診增量趨勢圖等。

(1)全國疫情數據

全國疫情數據以文字形式顯示全國實時的疫情數據,包括確診人數,治愈人數,死亡人數,疑似人數。

img

(2)全國疫情統計圖

全國疫情數據是在全國地圖上使用不同的顏色代表大概確診人數區間,顏色的深淺表示疫情的嚴重程度,可以直觀了解高危區域。鼠標移到每個省份會高亮顯示,並展示該省份的名稱、確診人數、治愈人數、死亡人數。

img

(3)全國確診總量趨勢圖、全國確診增量趨勢圖

全國確診總量趨勢圖以折線統計圖的方式顯示全國確診的總量的趨勢,橫坐標為日期,縱坐標為確診人數。並且當鼠標懸浮在某某天的時候會顯示該天的日期、確診、治愈、死亡數據。

同樣,全國確診增量趨勢圖也以折線統計圖的方式顯示全國確診的增量的趨勢,橫坐標為日期,縱坐標為增量人數。並且當鼠標懸浮在某某天的時候會顯示該天的日期、確診、治愈、死亡數據。

img

(4)總覽

img

3.分省頁面

分省頁面主要包含各省疫情數據、各省確診總量趨勢圖、各省確診增量圖、省內各市確診,治愈,死亡人數的詳細數據以及實時疫情新聞等。

(1)各省疫情數據

各省疫情數據以文字形式顯示各省實時的疫情數據,包括確診人數,治愈人數,死亡人數,疑似人數。頁面提供選擇框,用戶可以根據需要選擇需要查詢的省份來查看目標省份的具體數據。

img

(2)各省確診總量趨勢圖、各省確診增量圖

各省確診總量趨勢圖以折線統計圖的方式顯示各省確診的總量的趨勢,橫坐標為日期,縱坐標為確診人數。並且當鼠標懸浮在某某天的時候會顯示該天的具體數據。

同樣各省確診增量趨勢圖也以折線統計圖方式顯示各省的確診的總量的趨勢,很坐標為日期,縱坐標為確診人數增量。並且當鼠標懸浮在某某天的時候會顯示該天的具體數據。

img

(3)省內各市的詳細數據

省內各市的詳細數據顯示各市的確診,治愈,死亡人數。

img

(4)疫情實時新聞

疫情實時新聞顯示主流媒體播報的疫情新聞,用戶可以點擊相應的標題查看對應的新聞

img

(5)總覽

img

二、實現

1.討論

img

img

img

img

img

img

img

img

2、功能結構圖

疫情統計系統主要分為兩個頁面,分別為全國頁面和分省頁面。全國頁面主要包含全國疫情數據、全國疫情統計圖、全國確診總量趨勢圖、全國確診增量趨勢圖等。分省頁面主要包含各省疫情數據、各省確診總量趨勢圖、各省確診增量圖、省內各市確診,治愈,死亡人數的詳細數據以及實時疫情新聞等。

img

3.設計實現過程

本次疫情統計可視化設計主要分為兩個頁面。一個是全國頁面,還有一個是分省頁面。通過我們的分析,全國頁面主要包含以下功能:查看全國疫情數據、查看全國疫情統計圖、查看全國確診總量趨勢圖、查看全國確診增量趨勢圖。分省頁面主要包含以下功能:查看各省疫情數據、查看各省確診總量趨勢圖、查看各省確診增量圖、查看省內各市確診,治愈,死亡人數的詳細數據以及查看實時疫情新聞。下面分別講述以上功能的實現

(1)全國頁面

  • 查看全國疫情數據

    調用接口https://lab.ahusmart.com/nCoV/api/overall?latest=1,使用var data = res.results[0];獲取json的值,data.confirmedCount data.curedCount data.deadCount data.suspectedCount分別獲取全國確診人數、全國治愈人數、全國死亡人數

  • 查看全國疫情統計圖

    使用china.js顯示中國地圖,使用node.js實現爬蟲,然后將爬取的數據放入地圖中。具體如下:

    • spider.js

      url指定請求的目標網站url = https://ncov.dxy.cn/ncovh5/view/pneumonia,分析目標頁面DOM結構,找到所要抓取的信息的相關DOM元素,提取對應疫情數據

    • index.js

      先引入express,再創建服務器應用,用app.get監聽請求,加入res.setHeader("Access-Control-Allow-Origin","*")解決跨域問題,最后用app.listen分配端口號啟動服務

    • 將filterData傳入到echarts中

  • 全國確診總量趨勢圖、全國確診增量趨勢圖

    調取api實現疫情數據的獲取,在series中用data注入數據,使用echart實現折線統計圖的顯示。

(2)分省頁面

  • 查看各省疫情數據

    調用接口'https://lab.ahusmart.com/nCoV/api/overall?latest=1&province=' + province獲取各省份數據,使用 var confirm 存放各省確診數據,var suspectedCount存放各省疑似數據,var curedCount 存放治愈數據var deadCount存放死亡數據。遍歷從接口獲取的數據,統計總的確診,疑似,治愈,死亡數據。

  • 查看全國確診總量趨勢圖、全國確診增量趨勢圖

    調取api實現疫情數據的獲取,在series中用data注入數據,使用echart實現折線統計圖的顯示。

  • 查看實時疫情新聞

    直接調取爬取的數據並展示數據

  • 查看省內各市確診,治愈,死亡人數的詳細數據

    直接調取爬取的數據並展示數據

四.關鍵代碼

1.country.html

(1)頁面總體結構

在這里插入圖片描述

(2)獲取全國的總數據

  • 調用接口https://lab.ahusmart.com/nCoV/api/overall?latest=1 在這里插入圖片描述

  • var data = res.results[0];獲取json的值

  • data.confirmedCount data.curedCount data.deadCount data.suspectedCount分別獲取全國確診人數、全國治愈人數、全國死亡人數

var dataUrl = "https://lab.ahusmart.com/nCoV/";
var dataUrlBackup = "https://lab.ahusmart.com/nCoV/";

$(document).ready(function() {
initCoreData();
initTrendChart();
initAddChart();
});
var initCoreData = function(province) {

$.ajax({
url: dataUrl + 'api/overall?latest=1',
type: 'get',
success: function(res) {
if(res.success === true) {
var data = res.results[0];

var html = ' 全國疫情數據:\n' +
'       <div>' +
'<span class="label label-warning data-confirmed">確診</span>:' + data.confirmedCount + '&nbsp;&nbsp;' +
'<span class="label label-success data-cured">治愈</span>:' + data.curedCount + ' &nbsp;&nbsp; ' +
'<span class="label label-danger data-dead">死亡</span>:' + data.deadCount + '&nbsp;&nbsp;' +
'<span class="label label-info data-dead">疑似</span>:' + data.suspectedCount + '</div>\n' +
' ';

$(".core-data").html(html);

return;
}
alert("獲取數據失敗");

},
error: function(res) {
if(res.state() === "rejected" && !this.url.includes(dataUrlBackup)) {
this.url = this.url.replace(dataUrl, dataUrlBackup);
$.ajax(this);
}
}
})

};

(3)地圖的實現

用node.js實現爬蟲

spider.js

  • url指定請求的目標網站url = https://ncov.dxy.cn/ncovh5/view/pneumonia

  • 分析目標頁面DOM結構,找到所要抓取的信息的相關DOM元素

  • 提取對應疫情數據

//使用superagent請求目標頁面
const superagent = require('superagent')
//使用cheerio獲取頁面元素,獲取目標數據
const cheerio = require('cheerio')
const fs = require('fs')
const path = require('path')


const url = `https://ncov.dxy.cn/ncovh5/view/pneumonia`
superagent
.get(url)
.then(res => {
 
   const $ = cheerio.load(res.text)
   
   var $getListByCountryTypeService1 = $('#getListByCountryTypeService1').html()
   var $getAreaStat = $('#getAreaStat').html()
   var $getStatisticsService = $('#getStatisticsService').html()
   
   var dataObj = {}
   eval($getListByCountryTypeService1.replace(/window/g, 'dataObj'))
   eval($getAreaStat.replace(/window/g, 'dataObj'))
   eval($getStatisticsService.replace(/window/g, 'dataObj'))
 
//寫入本地
   fs.writeFile(path.join(__dirname, './data.json'), JSON.stringify(dataObj), err => {
     if (err) throw err
     console.log('數據寫入成功')
  })
})
.catch(err => {
   throw err
})

index.js

  • 先引入express

  • 再創建服務器應用

  • 用app.get監聽請求

  • 加入res.setHeader("Access-Control-Allow-Origin","*");解決跨域問題

  • 最后用app.listen分配端口號啟動服務

const express = require('express')
const fs = require('fs')
const path = require('path')
const app = express()
app.get('/api/data', (req, res) => {
res.setHeader("Access-Control-Allow-Origin","*");
 fs.readFile(path.join(__dirname, './data.json'), 'utf8', (err, data) => {
   if (err) throw err
   console.log(data)
   res.send(data)
})
})
app.listen(8066, () => {
 console.log(`啟動成功 http://127.0.0.1:8066/api/data`)
})
  • 獲取filterData 在這里插入圖片描述

  • 將filterData傳入到echarts中

    在這里插入圖片描述

(4)全國總量曲線圖的echarts實現

  • 獲取數據 在這里插入圖片描述

  • 在series中用data注入數據

    echartsOption = {
    backgroundColor: '#ddf4df',
    title: {
    text: '全國總量',
    textStyle: {
    fontWeight: 'normal',
    fontSize: 12,
    color: '#161916'
    },
    left: '2%'
    },
    tooltip: {
    trigger: 'axis',
    axisPointer: {
    lineStyle: {
    color: '#57617B'
    }
    }
    },
    legend: {
    icon: 'rect',
    itemWidth: 14,
    itemHeight: 5,
    itemGap: 1,
    data: ['確診', '治愈', '死亡'],
    right: '2%',
    textStyle: {
    fontSize: 12,
    color: '#161916'
    }
    },
    grid: {
    left: '2%',
    right: '2%',
    bottom: '2%',
    containLabel: true
    },
    xAxis: [{
    type: 'category',
    boundaryGap: false,
    axisLine: {
    lineStyle: {
    color: '#57617B'
    }
    },
    data: date
    }],
    yAxis: [{
    type: 'value',
    axisTick: {
    show: false
    },
    axisLine: {
    lineStyle: {
    color: '#57617B'
    }
    },
    axisLabel: {
    margin: 4,
    textStyle: {
    fontSize: 8
    }
    },
    splitLine: {
    lineStyle: {
    color: '#161916'
    }
    }
    }],
    series: [{
    name: '確診',
    type: 'line',
    smooth: true,
    symbol: 'circle',
    symbolSize: 5,
    showAllSymbol: false,
    lineStyle: {
    normal: {
    width: 1
    }
    },
    label: {
    show: true,
    position: 'top',
    textStyle: {
    color: '#fff'
    }
    }, areaStyle: {
    normal: {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
    offset: 0,
    color: 'rgba(137, 189, 27, 0.3)'
    }, {
    offset: 0.8,
    color: 'rgba(137, 189, 27, 0)'
    }], false),
    shadowColor: 'rgba(0, 0, 0, 0.1)',
    shadowBlur: 10
    }
    },
    itemStyle: {
    normal: {
    color: '#f1a325',
    borderColor: 'rgba(137,189,2,0.27)',
    borderWidth: 12

    }
    },
    data: confirmedNCoV
    }, {
    name: '治愈',
    type: 'line',
    smooth: true,
    symbol: 'circle',
    symbolSize: 5,
    showSymbol: false,
    lineStyle: {
    normal: {
    width: 1
    }
    },
    areaStyle: {
    normal: {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
    offset: 0,
    color: 'rgba(0, 136, 212, 0.3)'
    }, {
    offset: 0.8,
    color: 'rgba(0, 136, 212, 0)'
    }], false),
    shadowColor: 'rgba(0, 0, 0, 0.1)',
    shadowBlur: 10
    }
    },
    itemStyle: {
    normal: {
    color: '#38b03f',
    borderColor: 'rgba(0,136,212,0.2)',
    borderWidth: 12

    }
    },
    data: curedNCoV
    }, {
    name: '死亡',
    type: 'line',
    smooth: true,
    symbol: 'circle',
    symbolSize: 5,
    showSymbol: false,
    lineStyle: {
    normal: {
    width: 1
    }
    },
    areaStyle: {
    normal: {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
    offset: 0,
    color: 'rgba(0, 136, 212, 0.3)'
    }, {
    offset: 0.8,
    color: 'rgba(0, 136, 212, 0)'
    }], false),
    shadowColor: 'rgba(0, 0, 0, 0.1)',
    shadowBlur: 10
    }
    },
    itemStyle: {
    normal: {
    color: '#ea644a',
    borderColor: 'rgba(0,136,212,0.2)',
    borderWidth: 12

    }
    },
    data: deadNCoV
    }]
    };

2.specific.html

(1)省份確診,疑似,治愈,死亡數據統計

echartsOption = {
backgroundColor: '#ddf4df',
title: {
text: '全國總量',
textStyle: {
fontWeight: 'normal',
fontSize: 12,
color: '#161916'
},
left: '2%'
},
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#57617B'
}
}
},
legend: {
icon: 'rect',
itemWidth: 14,
itemHeight: 5,
itemGap: 1,
data: ['確診', '治愈', '死亡'],
right: '2%',
textStyle: {
fontSize: 12,
color: '#161916'
}
},
grid: {
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#57617B'
}
},
data: date
}],
yAxis: [{
type: 'value',
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#57617B'
}
},
axisLabel: {
margin: 4,
textStyle: {
fontSize: 8
}
},
splitLine: {
lineStyle: {
color: '#161916'
}
}
}],
series: [{
name: '確診',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showAllSymbol: false,
lineStyle: {
normal: {
width: 1
}
},
label: {
show: true,
position: 'top',
textStyle: {
color: '#fff'
}
},
    areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(137, 189, 27, 0.3)'
}, {
offset: 0.8,
color: 'rgba(137, 189, 27, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
},
itemStyle: {
normal: {
color: '#f1a325',
borderColor: 'rgba(137,189,2,0.27)',
borderWidth: 12

}
},
data: confirmedNCoV
}, {
name: '治愈',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 136, 212, 0.3)'
}, {
offset: 0.8,
color: 'rgba(0, 136, 212, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
},
itemStyle: {
normal: {
color: '#38b03f',
borderColor: 'rgba(0,136,212,0.2)',
borderWidth: 12

}
},
data: curedNCoV
}, {
name: '死亡',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 136, 212, 0.3)'
}, {
offset: 0.8,
color: 'rgba(0, 136, 212, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
},
itemStyle: {
normal: {
color: '#ea644a',
borderColor: 'rgba(0,136,212,0.2)',
borderWidth: 12

}
},
data: deadNCoV
}]
};

(2)省份每日數據統計

var initChart = function(province) {
$.ajax({
url: dataUrl + 'api/area?latest=0&province=' + province,
type: 'get',
success: function(res) {
if(res.success === true) {
var chartData = res.results;
var dateTrend = [];
var dateAdd = [];
var confirm = [];
var confirmAdd = [];
var datalist = [];

for(var i in chartData) {
var dataTime = new Date(chartData[i].updateTime);
var showTime = [dataTime.getFullYear(), dataTime.getMonth() + 1, ("0" + dataTime.getDate()).slice(-2)].join('/');
if(dateTrend.includes(showTime)) {
continue;
}
if(!datalist[showTime] || datalist[showTime] < chartData[i].confirmedCount) {
datalist[showTime] = chartData[i].confirmedCount;
}

}

// 時間排序
const dataListOrdered = {};
Object.keys(datalist).sort((function(a, b) {
a = a.split('/').join('');
b = b.split('/').join('');
return a > b ? 1 : a < b ? -1 : 0;
})).forEach(function(key) {
dataListOrdered[key] = datalist[key];
});

// 使用數據
for(var i in dataListOrdered) {
dateTrend.push(i);
confirm.push(dataListOrdered[i]);

var t = new Date(i);
t.setDate(t.getDate() - 1);
var yesterday = [t.getFullYear(), t.getMonth() + 1, ("0" + t.getDate()).slice(-2)].join('/');
if(!dataListOrdered[yesterday]) {
continue;
}

dateAdd.push(i);
confirmAdd.push(dataListOrdered[i] - dataListOrdered[yesterday]);
}

var title = "確診總量(" + chartData[0].country + "-" + chartData[0].provinceShortName + ")";
initTrendChart(dateTrend, confirm, title);

title = "確診增量(" + chartData[0].country + "-" + chartData[0].provinceShortName + ")";
initAddChart(dateAdd, confirmAdd, title);
return;
}
alert("獲取數據失敗");
},
});

五、心路歷程與收獲

  • 021700915

    • 心路歷程:通過兩次結對實踐我的確收獲很多,最重要的是增強了團隊合作的意識。之前一直是一個人寫代碼,剛開始要合作的時候我還是非常疑惑的,質疑團隊合作的意義。既然自己都知道思路,還不如自己寫,和隊友溝通的時間都能寫很多,團隊合作還有什么意義呢?但是通過一次的團隊編程和兩次的結對合作,我意識到了自身想法的錯誤。好的團隊合作可以提高編程效率,加快項目的進度。同時,好的團隊也有利於每個團隊成員的自身的發展。通過團隊內的溝通學習,可以使自己學習到以前沒有接觸到的或者不熟悉的新技術,並且還可以獲取到完全不一樣的idea,獲得靈感。隊友之間還可以相互監督,相互帶動,確保能夠按時完成任務。就像此次實踐,以往我一般都是在deadline前一兩天去完成作業,這次提前了,有很多不會的隊友也耐心的解答。

    • 收獲: 通過本次結對實踐,我學到了很多東西。

      首先是進一步了解了GitHub的使用,對GitHub的作用加深了了解,對使用分支、release、issues、pr等其它功能有了更加深入的了解。GitHub的確是一個團隊編程的好平台,能夠提高編程效率,避免相互傳文件的麻煩。

      其次是鞏固了前端知識,學習了一些新的知識。雖然說在上學期已經學習了前端的一些技術,如html,javascript,css等,但是到現在也有一些遺忘。通過此次實踐鞏固了這些知識,尤其是JavaScript部分的知識,因為本次實踐大量使用JavaScript語言編寫。同時,又學習了一些新知識,如echart的使用,echart各個屬性的設置,node.js爬蟲的一些相關知識。

      最后是對結對編程有了進一步的認識,對結對編程的意義有了更加深入的了解。相互學習,相互監督,相互促進,提升效率。

    • 隊友評價:隊友執行力很強,總是在任務布置后的一兩天開始做(而不像我,在deadline前才開始着手完成),這直接加快了本次作業的完成進度。隊友的編程能力也很強,對於很多沒學過的技術也有了解(node.js),並且能夠運用該技術,然而我卻不怎么了解。但是在隊友大量文字以及發視頻的耐心講解下我對該技術有了更加深入的了解,所以我認為這是一位非常盡職,有責任心,耐心的隊友。

      img

  • 091700403

    • 收獲:此次作業完成后,我學會了Git分支操作,對爬蟲等知識也有了一定的了解。也接觸了echarts,了解了如何去通過圖表的形式將數據可視化表現出來,學習了前端的一些內容,又再次復習了HTML,CSS。在完成作業的過程中遇到了很多困難,比如如何去將爬取下來的內容進行截取,從中提取出所需要的數據內容。 通過此次結對合作,我更加深刻的體會到了團隊合作的重要性,在這個過程中,隊友也給了我很大的幫助。

    • 隊友評價:隊友做事認真負責,細心謹慎,在結對完成作業的過程中,從他身上我學會了更加耐心地去完成細節,我們也知道了如何去更好地溝通,去表達自己的想法,將自己的所思所想用語言表達清楚。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM