基本步骤:
- 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("服务启动成功");