基本步驟:
- node爬取數據
- 獲取標準數據
- 前臺數據標準化
- 展示
效果展示:
利用node爬取數據
爬取網站:丁香網
所要使用的node第三方模塊 01 superagent用於向目標網站發送請求並帶回數據。 02 cheerio可將返回的數據轉爲Jq的DOM樹。方便操作數據
利用superagent向目標網站發送請求。(ps:superagent爲promise對象)
先讓我們來看看它帶回來的是個什麼玩意兒。
superagent.get("https://ncov.dxy.cn/ncovh5/view/pneumonia").then(res => {
console.log(res);
})
密密麻麻的有些讓人頭大是不是,可是你仔細看一下便能發現規律。它返回的是一個個html標籤夾帶的數據。並且其分類很清楚。
看我們這裏所需要的數據,它被包含在id爲getAreaStat的這個script標籤裏面。我們所要用的具體數據在名爲window.getAreaStat的這個數組裏面。但是在node裏面是沒有window標籤。所以這裏我們要處理一下。用另一個字符代替這個window。
cheerio模塊的強大之處便可在這裏體現出來。
這裏我將取出的所需數據利用fs模塊寫入了一個文檔裏面,方便一會傳給前臺
superagent.get("https://ncov.dxy.cn/ncovh5/view/pneumonia").then(res => {
const $ = cheerio.load(res.text);
let $getAreaStat = $("#getAreaStat").html();
let obj = {};
let newGetAreaStat = $getAreaStat.replace(/window/g, "obj");
eval(newGetAreaStat);
//eval函數可將字符串參數作爲js語句執行,這裏執行完的結果是給obj添加了一個屬性,屬性值就是我們所需的數據
fs.writeFile(path.join(__dirname, "data.txt"), JSON.stringify(obj), err => {
if (err == null) {
console.log("寫入成功");
} else {
throw err;
}
});
})
創建服務器,設置響應數據
這裏比較常規,就不做解釋了
代碼:
const express = require("express");
const fs = require("fs");
const path = require("path");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/index", (req, res) => {
fs.readFile(path.join(__dirname, "data.txt"), "utf8", (err, doc) => {
res.send(doc);
});
});
app.listen(3000);
console.log("服務啓動成功");
訪問此路由查看:
前臺展示,藉助echarts
首先當然是要引入echarts所依賴的js文件。(去echarts官網拿一個便ok)
基本配置:
//準備一個容器
<div id="main" style="width: 600px;height:400px;"></div>
//初始化
let myChart = echarts.init(document.querySelector("#main"));
//相關配置
myChart.setOption({
//配置標題信息
title: {
text: '全國新冠疫情分佈情況',
left: 'center'
},
//配置鼠標經過展示信息
tooltip: {
formatter: params => {
return `地區:${params.name}<br/>現存確診:${params.value }人>`
}
},
//配置人數區間顏色等信息
visualMap: [{
type: 'piecewise', // continuous連續的 piecewise分段
pieces: [{
gt: 10000
}, // (10000, Infinity]
{
gt: 1000,
lte: 9999
}, // (1000, 9999]
{
gt: 100,
lte: 999
}, // (100, 999]
{
gt: 10,
lte: 99
}, // (10, 99]
{
gt: 0,
lte: 9
} // (0, 9]
],
inRange: {
color: ['#fdebcf', '#f59e83', '#e55a4e', '#cb2a2f', '#811c24']
}
}],
//配置圖表類型,以及數據
series: [{
type: "map",
map: "china",
label: {
// 覆蓋物設置
show: true
},
data: data
}]
})
注意其中的data的類型是有標準的。它必須是這樣的類型
[{name: '湖北', value: 5556},{name:"北京",value:"55"}...]
而剛纔我們在服務器準備的數據格式顯然不符合此標準。所以需要進行處理。
這裏我使用Ajax進行請求數據。
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:3000/index');
xhr.send();
xhr.onload = function() {
var data = [];
//服務器與瀏覽器之間的數據是以字符串格式相關傳遞的
var responseText = JSON.parse(xhr.responseText);
//用剛剛聲明的新數組,把裏面的對象格式轉換爲我們所需要的形式
responseText.getAreaStat.forEach(ele => {
data.push({
name: ele.provinceShortName,
value: ele.currentConfirmedCount,
curedCount: ele.curedCount,
deadCount: ele.deadCount
});
});
}
所有工作到這來已經全部完成
代碼
前臺所有代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/echarts.min.js">
</script>
<script src="js/china.js"></script>
</head>
<body>
<!-- 爲 ECharts 準備一個具備大小(寬高)的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
<script>
let myChart = echarts.init(document.querySelector("#main"));
// 指定圖表的配置項和數據
let newData = [];
var newArr;
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:3000/index');
xhr.send();
xhr.onload = function() {
var data = [];
var responseText = JSON.parse(xhr.responseText);
responseText.getAreaStat.forEach(ele => {
data.push({
name: ele.provinceShortName,
value: ele.currentConfirmedCount,
curedCount: ele.curedCount,
deadCount: ele.deadCount
});
});
myChart.setOption({
title: {
text: '全國新冠疫情分佈情況',
left: 'center'
},
tooltip: {
formatter: params => {
return `地區:${params.name}<br/>現存確診:${params.value }人<br/>治癒:${(params.data.curedCount ) || 0}人<br/>死亡:${params.data.deadCount||0}人<br/>`
}
},
visualMap: [{
type: 'piecewise', // continuous連續的 piecewise分段
pieces: [{
gt: 10000
}, // (10000, Infinity]
{
gt: 1000,
lte: 9999
}, // (1000, 9999]
{
gt: 100,
lte: 999
}, // (100, 999]
{
gt: 10,
lte: 99
}, // (10, 99]
{
gt: 0,
lte: 9
} // (0, 9]
],
inRange: {
color: ['#fdebcf', '#f59e83', '#e55a4e', '#cb2a2f', '#811c24']
}
}],
series: [{
type: "map",
map: "china",
label: {
// 覆蓋物設置
show: true
},
data: data
}]
})
}
</script>
</body>
</html>
後臺所有代碼:
- spider.js
const superagent = require("superagent");
const cheerio = require("cheerio");
const fs = require("fs");
const path = require("path");
superagent.get("https://ncov.dxy.cn/ncovh5/view/pneumonia").then(res => {
const $ = cheerio.load(res.text);
let $getAreaStat = $("#getAreaStat").html();
let obj = {};
let newGetAreaStat = $getAreaStat.replace(/window/g, "obj");
eval(newGetAreaStat);
fs.writeFile(path.join(__dirname, "data.txt"), JSON.stringify(obj), err => {
if (err == null) {
console.log("寫入成功");
} else {
throw err;
}
});
})
- 服務器 app.js
const express = require("express");
const fs = require("fs");
const path = require("path");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/index", (req, res) => {
fs.readFile(path.join(__dirname, "data.txt"), "utf8", (err, doc) => {
res.send(doc);
});
});
app.listen(3000);
console.log("服務啓動成功");