node联合echarts简单实现疫情地图

基本步骤:

  1. node爬取数据
  2. 获取标准数据
  3. 前台数据标准化
  4. 展示

效果展示:
在这里插入图片描述

利用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("服务启动成功");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值