前言

疫情远比我们在年初想的发展迅速,在过年前还计划着可以亲戚聚聚,结果都泡汤了,开始了自家游。

在初三的时候,看到那个丁香医生,觉得不够详细,比如说我想看下周边城市的疫情情况,但是我地理不好,根本不清楚其他城市的位置。

当时我想的是做一张地图标注各个城市的数量,及严重程度。然后我用python去爬虫,晚上成功了,第二点防爬了。当然拦不住我的,我使用元素爬取的方式也行。

但是这种方式需要运行crome内核渲染,然后要隔一段时间更新,我已经放弃了我买的windows,原因是贵,且自己贫苦。

当时我认为疫情很快会得到控制,所以我就放弃了。

前几天在博客园看到有人写了一个爬取的demo,那个api返回的数据相当标准,所以我有产生了想法。

看下我做的效果吧:



密密麻麻的,这是啥呢?完全没有可视度。

放大分析下。

1.我根据中国不同的省份,根据不同人数显示不同的颜色,且放上去会显示当前疫情。



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

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

放大后效果如下图:



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

正文

第一步

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

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

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

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

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

  1. public class AreaTree
  2. {
  3. public AreaTree()
  4. {
  5. this.Today = new Today();
  6. this.Total = new Overview();
  7. this.Children = new List<Children>();
  8. }
  9. //国家名字
  10. public string Name { get; set; }
  11. //今天的变化情况
  12. public Today Today { get; set; }
  13. //总数量
  14. public Overview Total { get; set; }
  15. //省或者直辖市
  16. public List<Children> Children { get; set; }
  17. }
  1. public class Children
  2. {
  3. //省名或者直辖市名
  4. public string Name { get; set; }
  5. // 今日变化
  6. public Today Today { get; set; }
  7. // 统计
  8. public Overview Total { get; set; }
  9. //省下面的区,直辖市下面的区
  10. public List<Children> children { get; set; }
  11. }

模型就是这样的。

第二步

我需要确定每个地方的经纬度,这样我才能在地图上定位.

这时候我想到了百度地图。

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

这个时候需要你去百度地图注册你的key了,免费哈。

看下mapv3模型,在这里我只介绍用到的经纬度,其他的自己看官网。吐槽一下,官网的文档绝对是程序员写的。

  1. public class mapv3
  2. {
  3. public int status { get; set; }
  4. public result result { get; set; }
  5. }

status 为状态0就ok,其他不ok。

看下result:

  1. public class result
  2. {
  3. public location location { get; set; }
  4. public int precise { get; set; }
  5. public int confidence { get; set; }
  6. public int comprehension { get; set; }
  7. public string level { get; set; }
  8. }

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

  1. public class location
  2. {
  3. public double lng { get; set; }
  4. public double lat { get; set; }
  5. }

这两个就是经纬度。

第三步

整理数据与echarts数据格式相对应,echarts是可视化的插件。

echarts经纬度是这样的格式:

{

"位置":[经,纬]

}

经纬度地址需要存取。

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

我使用dictionary,因为我需要鉴别是否已经存在了,方便查询。

下面是整体格式化:

  1. private static void GetPositionOfJson(IList<AreaTree> areaTrees)
  2. {
  3. // 考虑到查询成本
  4. echartsModels = new List<EchartsModel>();
  5. echartsMapModels = new List<EchartsMapModel>();
  6. pronvincedic =new List<EchartsModel>();
  7. EchartsModel echartsModel = new EchartsModel();
  8. EchartsMapModel echartsMapModel = new EchartsMapModel();
  9. foreach (var country in areaTrees)
  10. {
  11. var CountryName = country.Name;
  12. if (CountryName != "中国")
  13. {
  14. //only china 其他国家不管
  15. continue;
  16. }
  17. var provinceRank = "省";
  18. foreach (var province in country.Children)
  19. {
  20. if (province.Name == "北京" || province.Name == "天津" || province.Name == "上海" || province.Name == "重庆")
  21. {
  22. provinceRank = "市";
  23. }
  24. var provinceName = province.Name + provinceRank;
  25. //加入统计 因为西藏省区
  26. if (!dic.Keys.Contains(province.Name))
  27. {
  28. var fullName = provinceName + province.Name;
  29. mapv3 mapv3 = GetHttpRequest(fullName);
  30. if (mapv3.status == 0)
  31. {
  32. var location = mapv3.result.location;
  33. double[] d = new double[] { location.lng, location.lat };
  34. dic.Add(province.Name, d);
  35. }
  36. }
  37. EchartsModel echartsModelPClone = (EchartsModel)echartsModel.clone();
  38. echartsModelPClone.name = province.Name;
  39. echartsModelPClone.value = province.Total.Confirm;
  40. pronvincedic.Add(echartsModelPClone);
  41. //颜色
  42. EchartsMapModel echartsMapModelClone = (EchartsMapModel)echartsMapModel.clone();
  43. echartsMapModelClone.name = province.Name;
  44. //总感染人数
  45. EchartsModel InfectSum = (EchartsModel)echartsModel.clone();
  46. InfectSum.name = "感染人数";
  47. InfectSum.value = province.Total.Confirm;
  48. //治愈人数
  49. EchartsModel CureSum = (EchartsModel)echartsModel.clone();
  50. CureSum.name = "治愈人数";
  51. CureSum.value = province.Total.Heal;
  52. //沉重的死亡人数
  53. EchartsModel HeadSum = (EchartsModel)echartsModel.clone();
  54. HeadSum.name = "死亡人数";
  55. HeadSum.value = province.Total.Dead;
  56. List<EchartsModel> echartsModelMapList = new List<EchartsModel>();
  57. echartsModelMapList.Add(InfectSum);
  58. echartsModelMapList.Add(CureSum);
  59. echartsModelMapList.Add(HeadSum);
  60. echartsMapModelClone.value = echartsModelMapList;
  61. echartsMapModels.Add(echartsMapModelClone);
  62. foreach (var city in province.children)
  63. {
  64. if (!dic.Keys.Contains(city.Name))
  65. {
  66. var fullName = provinceName + city.Name;
  67. mapv3 mapv3 = GetHttpRequest(fullName);
  68. if (mapv3.status == 0)
  69. {
  70. var location = mapv3.result.location;
  71. double[] d = new double[] { location.lng, location.lat };
  72. dic.Add(city.Name, d);
  73. }
  74. }
  75. //后续需要优化部分
  76. EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
  77. echartsModelClone.name = city.Name;
  78. echartsModelClone.value = city.Total.Confirm;
  79. echartsModels.Add(echartsModelClone);
  80. }
  81. }
  82. }
  83. }

分析下:

下面是装载经纬度的:

  1. foreach (var city in province.children)
  2. {
  3. if (!dic.Keys.Contains(city.Name))
  4. {
  5. var fullName = provinceName + city.Name;
  6. mapv3 mapv3 = GetHttpRequest(fullName);
  7. if (mapv3.status == 0)
  8. {
  9. var location = mapv3.result.location;
  10. double[] d = new double[] { location.lng, location.lat };
  11. dic.Add(city.Name, d);
  12. }
  13. }
  14. //后续需要优化部分
  15. EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
  16. echartsModelClone.name = city.Name;
  17. echartsModelClone.value = city.Total.Confirm;
  18. echartsModels.Add(echartsModelClone);
  19. }

判断不包含,然后去通过百度查询。

EchartsModel 是传递echarts模型中的散点格式。

echarts格式是{name:"",value:""},这时候散点就会显示数字和名字了。

因为每个城市创建数量过多,所以我采用克隆的方式进行处理。

其他我就不介绍了,源码公开逻辑也不复杂。

有一个地方需要介绍下:

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

为什么我这么做,因为这几个是直辖市。

比如我要查询武汉经纬度,肯定湖北省武汉。

查询北京的朝阳区,肯定是北京市朝阳区。如果是输入北京朝阳区是不准的。

第四步

当我把经纬度,保存在字典中,我每次我重启的时候需要查询一次,这非常耗时,我将会保存为json格式,然后存在本地,重启的时候,我将会读取,这里我贴代码。

当然我启动的时候我要初始化,且数据必须动态更新哈,所以我每隔一个小时去更新数据。

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

第五步

前端根据数据渲染。

我个人觉得能够介绍的只有颜色和大小。

  1. visualMap: {
  2. show: true,
  3. min: 0,
  4. max: 2000,
  5. left: 'left',
  6. top: 'bottom',
  7. text: ['高', '低'], // 文本,默认为数值文本
  8. calculable: true,
  9. seriesIndex: [1],
  10. pieces: [{
  11. }],
  12. inRange: {
  13. color: ["#F2FE96",'#FFFF00', '#A5CC82',"#BF444C"], // 绿到黄到红
  14. }
  15. },

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

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

散点和气泡大小如下:

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

最大为50,最小为10。

下面是如果value>100,那么让它显示危险标志。

  1. {
  2. name: 'item>100',
  3. type: 'effectScatter',
  4. coordinateSystem: 'geo',
  5. data: convertData(data.sort(function (a, b) {
  6. return b.value - a.value;
  7. }).filter(function (item) {
  8. return item.value >= 100
  9. })
  10. )
  11. ,
  12. symbolSize: function (val) {
  13. num = (val[2] / 10);
  14. num = num > 50 ? 50 : num
  15. if (val[2] == 0) {
  16. num = 0;
  17. }
  18. return num;
  19. },
  20. showEffectOn: 'render',
  21. rippleEffect: {
  22. brushType: 'stroke'
  23. },
  24. hoverAnimation: true,
  25. label: {
  26. normal: {
  27. formatter: '{b}',
  28. position: 'right',
  29. show: false
  30. }
  31. },
  32. itemStyle: {
  33. normal: {
  34. color: 'red',
  35. shadowBlur: 10,
  36. shadowColor: 'red'
  37. }
  38. },
  39. zlevel: 1
  40. },

总结

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

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

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

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

github地址:

https://github.com/aoximin/ViralCollapse

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

  1. 如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀)

    原文:如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀) 我们都知道可以通过在 Visual Studio 中设置输出路径(OutputPath)来更改项目输 ...

  2. .NET6运行时动态更新限流阈值

    昨天博客园撑不住流量又崩溃了,很巧正在编写这篇文章,于是产生一个假想:如果博客园用上我这个限流组件会怎么样呢? 用户会收到几个429错误,并且多刷新几次就看到了内容,不会出现完全不可用. 还可以降低查 ...

  3. 微软Azure配置中心 App Configuration (三):配置的动态更新

    写在前面 我在前文: <微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core>已经介绍了Asp.net Core怎么轻易的接入azure ...

  4. JSPatch – 动态更新iOS APP

    原文:http://blog.cnbang.net/works/2767/ JSPatch是最近业余做的项目,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的 ...

  5. JAVA代码热部署,在线不停服动态更新

    本地debug的时候,可以实时编译并更新代码,线上也可以不停服来动态更新类,即所说的java热部署.   JDK代理的两种方式: 1.premain方式是Java SE5开始就提供的代理方式,但其必须 ...

  6. elasticsearch同义词及动态更新

    第一种:参考地址:http://dev.paperlesspost.com/setting-up-elasticsearch-synonyms/271.Add a synonyms file.2.Cr ...

  7. 在Android中实现service动态更新UI界面

    之前曾介绍过Android的UI设计与后台线程交互,据Android API的介绍,service一般是在后台运行的,没有界面的.那么如何实现service动态更新UI界面呢?案例:通过service ...

  8. Android中动态更新ListView(转)

    在使用ListView时,会遇到当ListView列表滑动到最底端时,添加新的列表项的问题,本文通过代码演示如何动态的添加新的列表项到ListView中.实现步骤:调用ListView的setOnSc ...

  9. Js多国时间动态更新

    Js多国时间动态更新 点击下载

随机推荐

  1. 【小技巧】object上显示div

    这个现在不大常用了,就是object在页面中显示的优先级最高,其他层想覆盖在其上面,设置的z-index再高都不管用,解决办法是在层中加一个iframe.不多说了,直接记录下代码吧,估计以后用到的机率 ...

  2. $bzoj3872\ [Poi2014]\ Ant\ colony$ 二分+$dp$

    正解:二分+$dp$ 解题报告: 传送门$QwQ$ 一年过去了依然没有头绪,,,$gql$的$NOIp$必将惨败了$kk$. 考虑倒推,因为知道知道除数和答案,所以可以推出被除数的范围,然后一路推到叶 ...

  3. $SP703\ Mobile\ Service\ DP$

    洛谷 Sol 首先状态是已经完成的请求数量 这题只有三个员工跑来跑去,只有三个.... 一般像这种人数特别少的DP题就会把它们都放到状态里去 于是:f[i][x][y][z]表示现在已经完成了i个请求 ...

  4. k8s的简介以及搭建

    一:简介 1.什么是k8s? k8s是一个docker容器管理工具 它是一个全新的基于容器技术的分布式架构领先方案,是开源的容器集群管理系统. 在docker的基础上,为容器化的应用提供部署运行,资源 ...

  5. Linux gcc版本升级

    Linux gcc版本升级 操作环境 RHEL7,在进行内核编译时编译器版本,需要升级gcc编译器,选择gcc-8.3.0. http://ftp.gnu.org/gnu/gcc 里面提供所有的gcc ...

  6. ad域-iis

    环境准备: 1. win server 服务器安装完成 2.配置主机名 3.配置静态ip 安装ad域和iis 重启服务器 密码记住!!! 点击安装 把服务器的NDS设置成本机ip 重启完成 注意:ad ...

  7. 输入n个学生,并且输入成绩,判断是否偏科

    H学校的领导主任决定分析一下今年所有N名学生的考试成绩,从中找出偏科的学生,考试成绩包含语文,数学,英语三门课程的分数,已知偏科的定义是:某一门课程的分数大于等于90,并且另外两门的分数小于等于70. ...

  8. 深夜话题boot2docker还有那些隐藏MENU

    马克思的博士论文:自由意识的集中表达 --字体我设为5(18pt),你们懂的 总有人埋汰,终于我想起一个负负得正的话题 为什么放在深夜,因为希望看到的人越少越好,深夜是时差党的乐园 本篇作为之前几篇围 ...

  9. Elasticsearch如何修改Mapping结构并实现业务零停机

    Elasticsearch 版本:6.4.0 一.疑问 在项目中后期,如果想调整索引的 Mapping 结构,比如将 ik_smart 修改为 ik_max_word 或者 增加分片数量 等,但 El ...

  10. [bzoj2326] [洛谷P3216] [HNOI2011] 数学作业

    想法 最初的想法就是记录当前 \(%m\) 值为cur,到下一个数时 \(cur=cur \times 10^x + i\) n这么大,那就矩阵乘法呗. 矩阵乘法使用的要点就是有一个转移矩阵会不停的用 ...