新冠病毒疫情地圖實現


全國都在為新冠病毒戰斗,這是一場看不見硝煙的戰“疫”,每天醒來第一件事就是看疫情數據,然后就投入到戰“疫”工作中去。
期望拐點到來,比較直觀的就是疫情地圖,丁香園、頭條、高德、百度等都發布了疫情地圖數據,可以分地區查看疫情數據專題圖,用不同顏色表示確診病例數量,如何實現疫情地圖,參照丁香園網站,似乎用的mapbox工具展示地圖。
實現效果如下:
 
 
 
 
一、數據獲取存儲到數據庫
 
這里從丁香園抓取當天的疫情數據,用DJANGO 新建    coviddataprovince,coviddatacity model 表示各省和各市疫情數據。
 
 1 import os,django
 2 os.environ['DJANGO_SETTINGS_MODULE'] = 'covid.settings'
 3 django.setup()
 4 import urllib.request
 5 import requests
 6 import re
 7 from bs4 import BeautifulSoup
 8 from distutils.filelist import findall
 9 import json
10 from django.shortcuts import render
11 from coviddata.models import coviddataprovince,coviddatacity
12 from django.http import JsonResponse
13 import numpy
14 import psycopg2
15 
16 def getcoviddata():
17     url = "https://ncov.dxy.cn/ncovh5/view/pneumonia"
18     #url = "https://www.baidu.com"
19     headers = {  # 設置header
20         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
21         'Accept-Language': 'zh-CN,zh;q=0.8',
22         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
23     }
24     response = requests.get(url,headers=headers,timeout=30) # 以下是解析網頁的過程
25     htmlcontext = response.content
26     htmlcontext = str(htmlcontext, 'utf-8')
27     soup = BeautifulSoup(htmlcontext, "html.parser")
28     datas=soup.select('#getAreaStat')[0].get_text().replace("try { window.getAreaStat = ","").replace("}catch(e){}","")
29     jsondatas = json.loads(datas)
30     for jsondata in jsondatas:
31         province=coviddataprovince();
32         province.provinceName=jsondata["provinceName"];
33         province.provinceShortName = jsondata["provinceShortName"];
34         province.currentConfirmedCount =int( jsondata["currentConfirmedCount"]);
35         province.confirmedCount = int(jsondata["confirmedCount"]);
36         province.suspectedCount = int(jsondata["suspectedCount"]);
37         province.curedCount = int(jsondata["curedCount"]);
38         province.deadCount = int(jsondata["deadCount"]);
39         province.locationId = int(jsondata["locationId"]);
40         province.save();
41         for citydata in jsondata["cities"]:
42             city=coviddatacity();
43             city.cityName = citydata["cityName"];
44             city.currentConfirmedCount = int(citydata["currentConfirmedCount"]);
45             city.confirmedCount = int(citydata["confirmedCount"]);
46             city.suspectedCount = int(citydata["suspectedCount"]);
47             city.curedCount = int(citydata["curedCount"]);
48             city.deadCount = int(citydata["deadCount"]);
49             city.locationId = int(citydata["locationId"]);
50             city.save();
51 
52 def outcovidjson(request):
53     data = {}
54     coviddatas=coviddataprovince.objects.values()
55     data['coviddata'] = list(coviddatas)
56     return JsonResponse(data, safe=False, json_dumps_params={'ensure_ascii':False})
二、地圖展示
應用輕量級地圖工具Leafletjs展示地圖
 
  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4 <title>疫情防控地圖</title>
  5 <meta charset="utf-8" />
  6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7 <link rel="stylesheet" href="../static/gowhere/leaflet.css" />
  8 <link rel="stylesheet" href="../static/gowhere/screen.css" />
  9 <style>
 10     .info {
 11         padding: 6px 8px;
 12         font: 14px/16px Arial, Helvetica, sans-serif;
 13         background: white;
 14         background: rgba(255,255,255,0.8);
 15         box-shadow: 0 0 15px rgba(0,0,0,0.2);
 16         border-radius: 5px;
 17         width:200px;
 18         height:100px
 19     }
 20     .info h4 {
 21         margin: 0 0 5px;
 22         color: #777;
 23     }
 24     .legend {
 25         text-align: left;
 26         line-height: 18px;
 27         color: #555;
 28         width:150px;
 29     }
 30     .legend i {
 31         width: 18px;
 32         height: 18px;
 33         float: left;
 34         margin-right: 8px;
 35         opacity: 0.7;
 36     }
 37     .auto-style1 {
 38         width: 24px;
 39     }
 40     #coviddatainfo_province{
 41         font-size:20pt;
 42         line-height: 38px;
 43     }
 44     #coviddatainfo_confirm {
 45         font-size:14pt;
 46         line-height: 28px;
 47     }
 48     #coviddatainfo_cure {
 49         font-size:14pt;
 50         line-height: 28px;
 51     }
 52     td {
 53         width:150px;
 54     }
 55     .auto-style2 {
 56         height: 40px;
 57     }
 58 </style>
 59 </head>
 60 <body>
 61 <div id="map"></div>
 62 <script src="../static/gowhere/leaflet.js"></script>
 63 <script src="../static/gowhere/jquery-3.4.1.min.js"></script>
 64 <script src="../static/gowhere/leaflet.ChineseTmsProviders.js"></script>
 65 <script type="text/javascript" src="../static/gowhere/data/bou2_4p2.js"></script>
 66 <script type="text/javascript" src="../static/gowhere/data/chinaprovince.js"></script>
 67 <script type="text/javascript">
 68     var map = L.map('map').setView([35, 105], 3);
 69     var t11, t12,t13;
 70     var coviddata;
 71     L.tileLayer.chinaProvider('GaoDe.Normal.Map', { maxZoom: 9, minZoom: 3 }).addTo(map);
 72     // control that shows state info on hover
 73     var info = L.control();
 74     info.onAdd = function (map) {
 75         this._div = L.DomUtil.create('div', 'info');
 76         this.update();
 77         return this._div;
 78     };
 79     info.update = function (props) {
 80         this._div.innerHTML = '<h4></h4>' + (props ? '<b>' + props.Name + '</b><br />確診:' + t12 + '<br/>疑似:' + t13 + '' : '選擇省份');
 81     };
 82     
 83     info.updatecontent=function(txt){
 84         this._div.innerHTML=txt;
 85     };
 86     info.addTo(map);
 87     // get color depending on population density value
 88     function getColor(d) {
 89         return d > 5000 ? '#FC4E2A' :
 90                d > 500 ? '#FD8D3C' :
 91                d > 300 ? '#FEB24C' :
 92                d > 200 ? '#FED976' :
 93                           '#FFEDA0';
 94     }
 95     function style(feature) {
 96         return {
 97             weight: 2,
 98             opacity: 1,
 99             color: 'white',
100             dashArray: '3',
101             fillOpacity: 0.7,
102             fillColor: getColor(getAch(feature))
103         };
104     }
105     function style2(feature) {
106         return {
107             weight: 2,
108             opacity: 1,
109             color: 'white',
110             dashArray: '3',
111             fillOpacity: 0.7,
112             fillColor: 'red'
113         };
114     }
115     function getAch(feature)
116     {
117         var provinceName=getProvince(feature.properties.Name);
118         //var t12 = updateField("All", "All", provinceName, table1, "2014YTD", "Ach%", null);
119         t12=getProvincevalue(feature.properties.Name,"confirmedCount");
120         return t12;
121     }
122     function highlightFeature(e) {
123         var layer = e.target;
124         layer.setStyle({
125             weight: 5,
126             color: '#666',
127             dashArray: '',
128             fillOpacity: 0.7
129         });
130         if (!L.Browser.ie && !L.Browser.opera) {
131             layer.bringToFront();
132         }
133         //info.update(layer.feature.properties);
134     }
135     var geojson,provicename="All";
136     function resetHighlight(e) {
137         geojson.resetStyle(e.target);
138         //info.update();
139     }
140     function zoomToFeature(e) {
141         //map.fitBounds(e.target.getBounds());
142         provicename = e.target.feature.properties.Name;
143         var currentConfirmedCount=getProvincevalue(provicename,"confirmedCount");
144         var curedCount=getProvincevalue(provicename,"curedCount");
145         //info.updatecontent(provicename+"確診病例:"+currentConfirmedCount+"治愈病例:"+curedCount);
146         $("#coviddatainfo_province").text("省名:"+provicename);
147         $("#coviddatainfo_confirm").text("確診病例:"+currentConfirmedCount);
148         $("#coviddatainfo_cure").text("治愈病例:"+curedCount);
149         //update();
150     }
151     function onEachFeature(feature, layer) {
152         layer.on({
153             mouseover: highlightFeature,
154             mouseout: resetHighlight,
155             click: zoomToFeature
156         });
157     }
158     function addcovidmap()
159     {
160         $(document).ready(function(){
161                 $.get("http://localhost/outcovidjson",function(data,status){
162                     //$("#test1").text("Hello world!");
163                     info.updatecontent("<div id='coviddatainfo_province'>所在省</div><div id='coviddatainfo_confirm'>確診病例</div><div id='coviddatainfo_cure'>治愈病例</div>");
164                     coviddata=data["coviddata"];
165                     geojson = L.geoJson(states, {
166                             style: style,
167                             onEachFeature: onEachFeature
168                     }).addTo(map);
169                 });
170         });
171     }
172     addcovidmap();
173     
174     map.attributionControl.addAttribution('');
175     var legend = L.control({ position: 'bottomright' });
176     legend.onAdd = function (map) {
177         var div = L.DomUtil.create('div', 'info legend'),
178             grades = [0,200,300,500,2000],
179             labels = [],
180             from, to;
181         for (var i = 0; i < grades.length; i++) {
182             from = grades[i];
183             to = grades[i + 1];
184             labels.push(
185                 '<i style="background:' + getColor(from + 1) + '"></i> ' +
186                 from + (to ? '&ndash;' + to : '+'));
187         }
188         div.innerHTML = labels.join('<br>');
189         return div;
190     };
191     legend.addTo(map);
192     function getProvince(name) {
193         for (var i = 0; i < chinaProvince.length; i++)
194             if (chinaProvince[i].Name == name)
195                 return chinaProvince[i].Pinyin;
196     }
197     function getProvincevalue(name,fieldname) {
198         for (var i = 0; i < coviddata.length; i++)
199             if (coviddata[i].provinceShortName == name)
200                 return coviddata[i][fieldname];
201     }
202 </script>
203 </body>
204 </html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM