全国疫情精准定点动态更新(.net core)

前言

疫情远比我们在年初想的发展迅速,在过年前还计划着可以亲戚聚聚,结果都泡汤了,开始了自家游。
在初三的时候,看到那个丁香医生,觉得不够详细,比如说我想看下周边城市的疫情情况,但是我地理不好,根本不清楚其他城市的位置。
当时我想的是做一张地图标注各个城市的数量,及严重程度。然后我用python去爬虫,晚上成功了,第二点防爬了。当然拦不住我的,我使用元素爬取的方式也行。
但是这种方式需要运行crome内核渲染,然后要隔一段时间更新,我已经放弃了我买的windows,原因是贵,且自己贫苦。
当时我认为疫情很快会得到控制,所以我就放弃了。
前几天在博客园看到有人写了一个爬取的demo,那个api返回的数据相当标准,所以我有产生了想法。
看下我做的效果吧:

密密麻麻的,这是啥呢?完全没有可视度。
放大分析下。
1.我根据中国不同的省份,根据不同人数显示不同的颜色,且放上去会显示当前疫情。

颜色可以通过左侧控制,上下有两个箭头可以上拉下拉,选取区域,如下图:

2.当地图放大后,可以看到更多的细节,比如说如果数量达到100后我就会让当前位置,加入警报,当然随着数量越多该位置的点更大,且冒泡提升更大。
放大后效果如下图:

好了看下大概思路吧,本博客只介绍思路,项目开源,写的随意,不要介意,地址在末尾贴出。

正文

第一步

我想的肯定是获取数据,在前几天看到一篇博客,上面介绍一个非常标准的api,我没有去找那篇博客了,在此感谢,如果该博主觉得需要贴出地址,请联系我,毕竟博文给与了我help。

HttpClient httpClient = new HttpClient { BaseAddress = new Uri("https://view.inews.qq.com/") };
HttpResponseMessage httpResponseMessage = httpClient.GetAsync("g2/getOnsInfo?name=disease_h5").GetAwaiter().GetResult();
var result = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
nCoVData data = JsonConvert.DeserializeObject<nCoVData>(result);
nCoVDataDetail nCoVDataDetail = JsonConvert.DeserializeObject<nCoVDataDetail>(data.Data);

通过格式化将json成c# 对象。

nCoVDataDetail.AreaTree 就是各个省的信息。

因为数量较多,我无法去截图数据在此介绍格式。

public class AreaTree
{
    public AreaTree()
    {
        this.Today = new Today();
        this.Total = new Overview();
        this.Children = new List<Children>();
    }
       //国家名字
    public string Name { get; set; }
        //今天的变化情况
    public Today Today { get; set; }
        //总数量
    public Overview Total { get; set; }
        //省或者直辖市
    public List<Children> Children { get; set; }
}
public class Children
{
     //省名或者直辖市名
    public string Name { get; set; }

    // 今日变化
    public Today Today { get; set; }
    // 统计
    public Overview Total { get; set; }
        //省下面的区,直辖市下面的区
    public List<Children> children { get; set; }
}

模型就是这样的。

第二步

我需要确定每个地方的经纬度,这样我才能在地图上定位.
这时候我想到了百度地图。

private static mapv3 GetHttpRequest(string areaAddress)
{
    HttpClient httpClient = new HttpClient { BaseAddress = new Uri("http://api.map.baidu.com/") };
    HttpResponseMessage httpResponseMessage = httpClient.GetAsync("geocoding/v3/?address=" + areaAddress + "&output=json&ak=你的key").GetAwaiter().GetResult();
    var result = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    mapv3 data = JsonConvert.DeserializeObject<mapv3>(result);
    return data;
}

这个时候需要你去百度地图注册你的key了,免费哈。
看下mapv3模型,在这里我只介绍用到的经纬度,其他的自己看官网。吐槽一下,官网的文档绝对是程序员写的。

public class mapv3
{
    public int status { get; set; }

    public result result { get; set; }
}

status 为状态0就ok,其他不ok。
看下result:

public class result
{
    public location location { get; set; }

    public int precise { get; set; }

    public int confidence { get; set; }

    public int comprehension { get; set; }

    public string level { get; set; }
}

其他不介绍了,用不上,详细看官网,在这里只介绍location。

public class location
{
    public double lng { get; set; }

    public double lat { get; set; }

}

这两个就是经纬度。

第三步

整理数据与echarts数据格式相对应,echarts是可视化的插件。
echarts经纬度是这样的格式:
{
"位置":[经,纬]
}
经纬度地址需要存取。

private static Dictionary<string, double[]> dic = new Dictionary<string, double[]>();

我使用dictionary,因为我需要鉴别是否已经存在了,方便查询。
下面是整体格式化:

private static void GetPositionOfJson(IList<AreaTree> areaTrees)
{
    // 考虑到查询成本
    echartsModels = new List<EchartsModel>();
    echartsMapModels = new List<EchartsMapModel>();
    pronvincedic =new List<EchartsModel>();
    EchartsModel echartsModel = new EchartsModel();
    EchartsMapModel echartsMapModel = new EchartsMapModel();
    foreach (var country in areaTrees)
    {
        var CountryName = country.Name;
        if (CountryName != "中国")
        {
            //only china 其他国家不管
            continue;
        }
        var provinceRank = "省";
        foreach (var province in country.Children)
        {
            if (province.Name == "北京" || province.Name == "天津" || province.Name == "上海" || province.Name == "重庆")
            {
                provinceRank = "市";
            }
            var provinceName = province.Name + provinceRank;

            //加入统计 因为西藏省区
            if (!dic.Keys.Contains(province.Name))
            {
                var fullName = provinceName + province.Name;
                mapv3 mapv3 = GetHttpRequest(fullName);
                if (mapv3.status == 0)
                {
                    var location = mapv3.result.location;
                    double[] d = new double[] { location.lng, location.lat };
                    dic.Add(province.Name, d);
                }
            }
            EchartsModel echartsModelPClone = (EchartsModel)echartsModel.clone();
            echartsModelPClone.name = province.Name;
            echartsModelPClone.value = province.Total.Confirm;
            pronvincedic.Add(echartsModelPClone);

            //颜色
            EchartsMapModel echartsMapModelClone = (EchartsMapModel)echartsMapModel.clone();
            echartsMapModelClone.name = province.Name;
            //总感染人数
            EchartsModel InfectSum = (EchartsModel)echartsModel.clone();
            InfectSum.name = "感染人数";
            InfectSum.value = province.Total.Confirm;
            //治愈人数
            EchartsModel CureSum = (EchartsModel)echartsModel.clone();
            CureSum.name = "治愈人数";
            CureSum.value = province.Total.Heal;
            //沉重的死亡人数
            EchartsModel HeadSum = (EchartsModel)echartsModel.clone();
            HeadSum.name = "死亡人数";
            HeadSum.value = province.Total.Dead;
            List<EchartsModel> echartsModelMapList = new List<EchartsModel>();
            echartsModelMapList.Add(InfectSum);
            echartsModelMapList.Add(CureSum);
            echartsModelMapList.Add(HeadSum);
            echartsMapModelClone.value = echartsModelMapList;
            echartsMapModels.Add(echartsMapModelClone);
            foreach (var city in province.children)
            {
                if (!dic.Keys.Contains(city.Name))
                {
                    var fullName = provinceName + city.Name;
                    mapv3 mapv3 = GetHttpRequest(fullName);
                    if (mapv3.status == 0)
                    {
                        var location = mapv3.result.location;
                        double[] d = new double[] { location.lng, location.lat  };
                        dic.Add(city.Name, d);
                    }
                }
                //后续需要优化部分
                EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
                echartsModelClone.name = city.Name;
                echartsModelClone.value = city.Total.Confirm;
                echartsModels.Add(echartsModelClone);
            }
        }
    }
}

分析下:
下面是装载经纬度的:

foreach (var city in province.children)
{
    if (!dic.Keys.Contains(city.Name))
    {
        var fullName = provinceName + city.Name;
        mapv3 mapv3 = GetHttpRequest(fullName);
        if (mapv3.status == 0)
        {
            var location = mapv3.result.location;
            double[] d = new double[] { location.lng, location.lat  };
            dic.Add(city.Name, d);
        }
    }
    //后续需要优化部分
    EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
    echartsModelClone.name = city.Name;
    echartsModelClone.value = city.Total.Confirm;
    echartsModels.Add(echartsModelClone);
}

判断不包含,然后去通过百度查询。
EchartsModel 是传递echarts模型中的散点格式。
echarts格式是{name:"",value:""},这时候散点就会显示数字和名字了。
因为每个城市创建数量过多,所以我采用克隆的方式进行处理。
其他我就不介绍了,源码公开逻辑也不复杂。
有一个地方需要介绍下:

if (province.Name == "北京" || province.Name == "天津" || province.Name == "上海" || province.Name == "重庆")
{
    provinceRank = "市";
}

为什么我这么做,因为这几个是直辖市。
比如我要查询武汉经纬度,肯定湖北省武汉。
查询北京的朝阳区,肯定是北京市朝阳区。如果是输入北京朝阳区是不准的。

第四步

当我把经纬度,保存在字典中,我每次我重启的时候需要查询一次,这非常耗时,我将会保存为json格式,然后存在本地,重启的时候,我将会读取,这里我贴代码。
当然我启动的时候我要初始化,且数据必须动态更新哈,所以我每隔一个小时去更新数据。

timer.LoadMap();
//初始化
timer.getData(null,null);
//每隔一小时执行一次
System.Timers.Timer  timerOneHour= new System.Timers.Timer(60 * 60 * 1000);
timerOneHour.Elapsed += new System.Timers.ElapsedEventHandler(timer.getData);
timerOneHour.AutoReset = true;

第五步

前端根据数据渲染。
我个人觉得能够介绍的只有颜色和大小。

visualMap: {
    show: true,
    min: 0,
    max: 2000,
    left: 'left',
    top: 'bottom',
    text: ['高', '低'], // 文本,默认为数值文本
    calculable: true,
    seriesIndex: [1],
    pieces: [{
    }],
    inRange: {
        color: ["#F2FE96",'#FFFF00', '#A5CC82',"#BF444C"], // 绿到黄到红
    }
},

设定省份的数量区间是0-2000,颜色在这区间变动:

color: ["#F2FE96",'#FFFF00', '#A5CC82',"#BF444C"]

散点和气泡大小如下:

symbolSize: function (val) {
    num = val[2] / 5;
    num = num > 50 ? 50 : num;
    num = num < 10 ? 10 : num;
    return num;
}

最大为50,最小为10。
下面是如果value>100,那么让它显示危险标志。

{
    name: 'item>100',
    type: 'effectScatter',
    coordinateSystem: 'geo',
    data: convertData(data.sort(function (a, b) {
        return b.value - a.value;
    }).filter(function (item) {
        return item.value >= 100
    })
    )
    ,
    symbolSize: function (val) {
        num = (val[2] / 10);
        num = num > 50 ? 50 : num
        if (val[2] == 0) {
            num = 0;
        }
        return num;
    },
    showEffectOn: 'render',
    rippleEffect: {
        brushType: 'stroke'
    },
    hoverAnimation: true,
    label: {
        normal: {
            formatter: '{b}',
            position: 'right',
            show: false
        }
    },
    itemStyle: {
        normal: {
            color: 'red',
            shadowBlur: 10,
            shadowColor: 'red'
        }
    },
    zlevel: 1
},

总结

愿疫情快速结束,带好口罩,保护自己,保护他人。人人为我,我为人人。

本来,我想在我的服务器上部署的,但是黑客太多,本人安全防护水平太低了。

所以上传到github,没有数据库,直接可运行。.net core 库,2.2,可自行更换,写的随意,见谅。

需要替换百度的key,因为我已经去掉了。如果实在不想去注册,可评论发到你的邮箱。

github地址:

https://github.com/aoximin/ViralCollapse

原文地址:https://www.cnblogs.com/aoximin/p/12298477.html

时间: 2024-08-30 15:25:44

全国疫情精准定点动态更新(.net core)的相关文章

全国疫情统计可视化地图(2)

第二阶段的要求是通过地图展示全国疫情的情况. 1:首先要下载中国地图的插件 china.js  ,由于目前Echarts官网已经不提供地图的下载.下面是echarts.min.js  china.js和各个省份地图的js的资源,方便大家下载. 链接: https://pan.baidu.com/s/1MFt-0LqAUQXzpiI1qy-Q0w 提取码: q7y4 2: 要将数据库中数据传进地图去,自然要书写相应的bean目录.dao层以及servlet.bean目录的话不用多说,和之前的代码一

Service 动态更新 UI

http://blog.csdn.net/u013724061/article/details/38642049 最终效果: 动态显示当前时间和电量 思路: 首先在Activity里用内部类定义两种广播,一种是系统广播(电池),另一种是自定义广播. private class SimpleBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent int

定时动态更新图表

在进行实现动态更新图表时主要使用AJAX技术,主要分两种实现方法,一种是通过ASP.NET特有的AJAX控件,UpdatePanel.Timer控件+ASP.NET自带的Chart控件实现:另一种为使用第三方的图表库+JQUERY\AJAX实现. ASP.NET控件实现 实现: 前台将要定时刷新的内容放到updatePanel中即可,前台代码如下: <form id="form1" runat="server"> <asp:ScriptManage

JSPatch – 动态更新iOS APP

博文转载至 http://blog.cnbang.net/works/2767/ JSPatch是最近业余做的项目,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug. 用途 是否有过这样的经历:新版本上线后发现有个严重的bug,可能会导致crash率激增,可能会使网络请求无法发出,这时能做的只是赶紧修复bug然后提交等待漫长的AppStore审核,再盼望用户快点升级,付出巨大的人力和

android中实现service动态更新UI界面

案例:通过service向远程服务器发送请求,根据服务器返回的结果动态更新主程序UI界面,主程序可实时关闭或重启服务. 注册BroadcastReceiver 在主程序activity中注册一个BroadcastReceiver,用于接收Service发布的广播. @Override protected void onStart() {//重写onStart方法 dataReceiver = new DataReceiver(); IntentFilter filter = new Intent

Android ListView动态更新数据

ListView就是可以显示一行行Item的控件,有时候数据非常多,通常需要分页显示,但为了减少用户的输入,我们可以动态更新ListView,把下一页要显示的数据的添加到当前ListView中. 先看看效果: 需要注意的是在什么时候去更新数据 ,listVIew的setOnScrollListener监听是否滚到了最后一条记录, 取到的数据加到list中,最后记得调用adapter的notifyDataSetChanged,通知listview改变. 不废话,上代码. 主文件: mport ja

手游的一些事儿 - 动态更新

标题本来想叫"手游那些事儿",想了想还是算了,不想盗用"明朝那些事儿" 的"招牌"(其实还是有盗用的嫌疑,哈哈).   为了抹掉打广告的嫌疑,这里暂以已经比较火的或者腾讯出品的游戏举例(外加吐槽) 腾讯的<游龙英雄> 游久的<酷酷爱魔兽> 腾讯的<怪物弹珠>   目前国内手游2d开发以cocos2d-x js/lua为主流,3d多使用unity3d,类似网易这种做过端游的游戏厂商则倾向于使用在端游已经成熟的引擎

android开发中 如何动态更新TextView的内容?

============问题描述============ 我想动态更新TextView内容,但是没有反应.有没有相关代码. ============解决方案1============ 写个定时器.或者写个线程.隔段时间去更新就哦了 ============解决方案2============ 引用 2 楼 tyaathome 的回复: Quote: 引用 1 楼 peijiangping1989 的回复: 写个定时器.或者写个线程.隔段时间去更新就哦了 有没有类似的代码例子给我看看. 新建个线程来

DNS&BIND——动态更新的DNS主从复制

本文配置的正向解析的主从服务,反向同理,不赘述了.... 从服务器应该是一台独立的名称服务器(首先要成为缓存服务器) 主动通知的必要条件(i或ii,满足其一即可) 主服务器的区域解析库文件中,必须有一条NS记录是指向从服务器(主动通知) master: vim  /etc/named.rfc1912.zones also-notify {slave_ip;}; 从服务器只需要定义区域.而无需提供解析库文件; 解析库文件自动同步至/var/named/slaves目录中 主服务器得允许从服务器作区