Django博客来访人员地域分布大数据可视化---echarts绘图、geoip2获取地理位置

文章目录

Django博客来访人员地域分布大数据可视化—echarts绘图、geoip2获取地理位置

今天,萌生一个想法。就是想把我的个人博客来访的人员地域分布进行一个可视化作图,并显示在我的留言板上。话不多说,就开始了掉头发的征程。。。。

效果

首先,还是来展示一下效果怎么样吧:

Django博客来访人员地域分布大数据可视化---echarts绘图、geoip2获取地理位置

生成的是一份中国地图,这里只统计了国内来访人员。鼠标放在相应的省份会弹出数据(如上所示),人数不同,显示的颜色深度不同。不可以放大缩小等。具体可以去我的博客查看(欢迎留言噢~):

https://www.liboer.top/messages/

echarts作图

这里使用百度的echarts

首先在留言页面先画出一个中国地图分布,先用假数据代替。后边再改为ajax从后端数据库拿数据。

去echarts官网下载两个js文件:echarts.js、echarts.min.js,此外还需要一个js,就是用来话中国地图的china.js

在此,有找不到的可以直接在此下载,我分享一下我的百度云,失效的话评论区联系我。

链接:https://pan.baidu.com/s/12cUE25QsxXTmi-Qu9zPWqw
提取码:9vzg
复制这段内容后打开百度网盘手机App,操作更方便哦

在我的留言页面引入,后用jq操作画图:

# 容器,图片显示的位置
<div id="main" style="width: 600px;height:400px;"></div>


{% block js %}	
	<script src="{% static 'js/echarts.js' %}"></script>
    <script src="{% static 'js/echarts.min.js' %}"></script>
    <script src="{% static 'js/china.js' %}"></script>


    <script>
        var optionMap = {
            backgroundColor: '#FFFFFF',
            backgroundColor: 'transparent',  // 背景透明色
            title: {
                text: '全国来访人员地域分布大数据',
                subtext: '',
                x:'center',
                textStyle:{
                    color: '#CFB53B',
                    fontfamily:'Microsoft YaHei'
                }
            },
            tooltip : {
                trigger: 'item'
            },

            //左侧小导航图标
            visualMap: {
                show : false,
                x: 'left',
                y: 'center',
                splitList: [
                    {start: 500, end:600},{start: 400, end: 500},
                    {start: 300, end: 400},{start: 200, end: 300},
                    {start: 100, end: 200},{start: 0, end: 100},
                ],
                color: ['#5475f5', '#9feaa5', '#85daef','#74e2ca', '#e6ac53', '#9fb5ea']
            },

            //配置属性
            series: [{
                name: '数据',
                type: 'map',
                mapType: 'china',
                roam: true,
                label: {
                    normal: {
                        show: true  //省份名称
                    },
                    emphasis: {
                        show: false
                    }
                },
                data:mydata  //数据
            }]
        };
        //初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));

        //使用制定的配置项和数据显示图表
        myChart.setOption(optionMap);
    </script>
 {% endblock %}

data数据

[
    {
        "name": "北京",
        "value": 104
    },
    {
        "name": "天津",
        "value": 31
    },
    {
        "name": "上海",
        "value": 432
    },
    {
        "name": "重庆",
        "value": 51
    },
    {
        "name": "河北",
        "value": 15
    },
    {
        "name": "河南",
        "value": 85
    },
    {
        "name": "云南",
        "value": 13
    },
    {
        "name": "辽宁",
        "value": 86
    },
    {
        "name": "黑龙江",
        "value": 22
    },
    {
        "name": "湖南",
        "value": 57
    },
    {
        "name": "安徽",
        "value": 231
    },
    {
        "name": "山东",
        "value": 212
    },
    {
        "name": "*",
        "value": 98
    },
    {
        "name": "江苏",
        "value": 561
    },
    {
        "name": "浙江",
        "value": 79
    },
    {
        "name": "江西",
        "value": 67
    },
    {
        "name": "湖北",
        "value": 63
    },
    {
        "name": "广西",
        "value": 16
    },
    {
        "name": "甘肃",
        "value": 65
    },
    {
        "name": "山西",
        "value": 3
    },
    {
        "name": "内蒙古",
        "value": 76
    },
    {
        "name": "陕西",
        "value": 22
    },
    {
        "name": "吉林",
        "value": 22
    },
    {
        "name": "福建",
        "value": 78
    },
    {
        "name": "贵州",
        "value": 189
    },
    {
        "name": "广东",
        "value": 345
    },
    {
        "name": "青海",
        "value": 52
    },
    {
        "name": "*",
        "value": 78
    },
    {
        "name": "四川",
        "value": 47
    },
    {
        "name": "宁夏",
        "value": 88
    },
    {
        "name": "海南",
        "value": 89
    },
    {
        "name": "*",
        "value": 83
    },
    {
        "name": "香港",
        "value": 33
    },
    {
        "name": "澳门",
        "value": 99
    }
]

此时,在页面中已经显示啦,但是静态的数据。我们要在后端把他动态化。

geoip2获取地理位置

geoip2可以获取ip所在的地理位置,我测试了一下,并不是所有的ip都能正常的得到地理位置,目前没找到好的替代品,先用这个吧。

安装

pip3 install geoip2

geoip2需要一个GeoLite2数据库文件,大家可以自行去官网下载。前边的百度与我也分享了。

# Django获取ip
request.META.get("REMOTE_ADDR")
# 拿到地理位置市
import geoip2.database
from BlogLee import settings
reader = geoip2.database.Reader(settings.GEOIP_PATH)
response = reader.city(ip)
city = response.city.names['zh-CN']
print(city)
# settings.GEOIP_PATH是GeoLite2数据库文件地址
# GEOIP_PATH = os.path.join(BASE_DIR, 'static', 'GeoLite2-City.mmdb')

我的Django博客所有的功能都已经实现,现在又有新的功能需要。我不可能再去查找改动。所以就写个装饰器吧!

此装饰器实现获取ip,拿到地理位置省份。并把数据存储到数据库中。之后把所有的视图中get方法用此装饰器装饰即可。

def ip_addr(func):
    def wrapper(request, *args, **kwargs):
        # print('meta', request.META)

        # print('测试', request.geo_data.ip_address)
        # print('request', request)
        ip = request.META.get("REMOTE_ADDR")
        # print(request.META.get("HTTP_X_FORWARDED_FOR"))
        print(ip)
        provence = provence

        reader = geoip2.database.Reader(settings.GEOIP_PATH)
        # response = reader.city(ip)

        day = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        try:
            # response = reader.city(ip)
            response = reader.city('88.5.237.10')
            city = response.city.names['zh-CN']
            print(city)
            flag = False
            pro = ''
            for k in provence.keys():
                for c in provence[k]:
                    if c == city + '市':
                        if k[-1] == '省':
                            pro = k[:-1]
                        else:
                            pro = k
                        flag = True
                        break
                if flag:
                    break
            print(pro)
            obj = models.Provence.objects.filter(name=pro).first()
            print(obj)
            if obj:
                obj.viewed()
            logs = f'ip正常。\nip:{ip}\n访问时间:{day}\n\n'
            path = 'uploads' + '/' + 'iplog' + '/' + 'normal_ip' + '.log'
            file_add(path, logs)
        except:
            path = 'uploads' + '/' + 'iplog' + '/' + 'anomaly_ip' + '.log'
            logs = f'ip异常,可能使用了代理。\nip:{ip}\n访问时间:{day}\n\n'
            file_add(path, logs)
            # print('ip异常')
        # print(response.country.names['zh-CN'], response.city.names['zh-CN'])
        res = func(request, *args, **kwargs)
        return res

    return wrapper

省份数据

{
            "河南省": [
                "郑州市",
                "洛阳市",
                "焦作市",
                "商丘市",
                "信阳市",
                "周口市",
                "鹤壁市",
                "安阳市",
                "濮阳市",
                "驻马店市",
                "南阳市",
                "开封市",
                "漯河市",
                "许昌市",
                "新乡市",
                "济源市",
                "灵宝市",
                "偃师市",
                "邓州市",
                "登封市",
                "三门峡市",
                "新郑市",
                "禹州市",
                "巩义市",
                "永城市",
                "长葛市",
                "义马市",
                "林州市",
                "项城市",
                "汝州市",
                "荥阳市",
                "平顶山市",
                "卫辉市",
                "辉县市",
                "舞钢市",
                "新密市",
                "孟州市",
                "沁阳市",
                "郏县"
            ],
            "安徽省": [
                "合肥市",
                "亳州市",
                "芜湖市",
                "马鞍山市",
                "池州市",
                "黄山市",
                "滁州市",
                "安庆市",
                "淮南市",
                "淮北市",
                "蚌埠市",
                "宿州市",
                "宣城市",
                "六安市",
                "阜阳市",
                "铜陵市",
                "明光市",
                "天长市",
                "宁国市",
                "界首市",
                "桐城市",
                "潜山市"
            ],
            "福建省": [
                "福州市",
                "厦门市",
                "泉州市",
                "漳州市",
                "南平市",
                "三明市",
                "龙岩市",
                "莆田市",
                "宁德市",
                "龙海市",
                "建瓯市",
                "武夷山市",
                "长乐市",
                "福清市",
                "晋江市",
                "南安市",
                "福安市",
                "邵武市",
                "石狮市",
                "福鼎市",
                "建阳市",
                "漳平市",
                "永安市"
            ],
            "甘肃省": [
                "兰州市",
                "白银市",
                "武威市",
                "金昌市",
                "平凉市",
                "张掖市",
                "嘉峪关市",
                "酒泉市",
                "庆阳市",
                "定西市",
                "陇南市",
                "天水市",
                "玉门市",
                "临夏市",
                "合作市",
                "敦煌市",
                "甘南州"
            ],
            "贵州省": [
                "贵阳市",
                "安顺市",
                "遵义市",
                "六盘水市",
                "兴义市",
                "都匀市",
                "凯里市",
                "毕节市",
                "清镇市",
                "铜仁市",
                "赤水市",
                "仁怀市",
                "福泉市"
            ],
            "海南省": [
                "海口市",
                "三亚市",
                "万宁市",
                "文昌市",
                "儋州市",
                "琼海市",
                "东方市",
                "五指山市"
            ],
            "河北省": [
                "石家庄市",
                "保定市",
                "唐山市",
                "邯郸市",
                "邢台市",
                "沧州市",
                "衡水市",
                "廊坊市",
                "承德市",
                "迁安市",
                "鹿泉市",
                "秦皇岛市",
                "南宫市",
                "任丘市",
                "叶城市",
                "辛集市",
                "涿州市",
                "定州市",
                "晋州市",
                "霸州市",
                "黄骅市",
                "遵化市",
                "张家口市",
                "沙河市",
                "三河市",
                "冀州市",
                "武安市",
                "河间市",
                "深州市",
                "新乐市",
                "泊头市",
                "安国市",
                "双滦区",
                "高碑店市"
            ],
            "黑龙江省": [
                "哈尔滨市",
                "伊春市",
                "牡丹江市",
                "大庆市",
                "鸡西市",
                "鹤岗市",
                "绥化市",
                "齐齐哈尔市",
                "黑河市",
                "富锦市",
                "虎林市",
                "密山市",
                "佳木斯市",
                "双鸭山市",
                "海林市",
                "铁力市",
                "北安市",
                "五大连池市",
                "阿城市",
                "尚志市",
                "五常市",
                "安达市",
                "七台河市",
                "绥芬河市",
                "双城市",
                "海伦市",
                "宁安市",
                "讷河市",
                "穆棱市",
                "同江市",
                "肇东市"
            ],
            "湖北省": [
                "武汉市",
                "荆门市",
                "咸宁市",
                "襄阳市",
                "荆州市",
                "黄石市",
                "宜昌市",
                "随州市",
                "鄂州市",
                "孝感市",
                "黄冈市",
                "十堰市",
                "枣阳市",
                "老河口市",
                "恩施市",
                "仙桃市",
                "天门市",
                "钟祥市",
                "潜江市",
                "麻城市",
                "洪湖市",
                "汉川市",
                "赤壁市",
                "松滋市",
                "丹江口市",
                "武穴市",
                "广水市",
                "石首市",
                "大冶市",
                "枝江市",
                "应城市",
                "宜城市",
                "当阳市",
                "安陆市",
                "宜都市",
                "利川市"
            ],
            "湖南省": [
                "长沙市",
                "郴州市",
                "益阳市",
                "娄底市",
                "株洲市",
                "衡阳市",
                "湘潭市",
                "岳阳市",
                "常德市",
                "邵阳市",
                "永州市",
                "张家界市",
                "怀化市",
                "浏阳市",
                "醴陵市",
                "湘乡市",
                "耒阳市",
                "沅江市",
                "涟源市",
                "常宁市",
                "吉首市",
                "津市市",
                "冷水江市",
                "临湘市",
                "汨罗市",
                "武冈市",
                "韶山市",
                "湘西州"
            ],
            "吉林省": [
                "长春市",
                "吉林市",
                "通化市",
                "白城市",
                "四平市",
                "辽源市",
                "*市",
                "白山市",
                "集安市",
                "梅河口市",
                "双辽市",
                "延吉市",
                "九台市",
                "桦甸市",
                "榆树市",
                "蛟河市",
                "磐石市",
                "大安市",
                "德惠市",
                "洮南市",
                "龙井市",
                "珲春市",
                "公主岭市",
                "图们市",
                "舒兰市",
                "和龙市",
                "临江市",
                "敦化市"
            ],
            "江苏省": [
                "南京市",
                "无锡市",
                "常州市",
                "扬州市",
                "徐州市",
                "苏州市",
                "连云港市",
                "盐城市",
                "淮安市",
                "宿迁市",
                "镇江市",
                "南通市",
                "泰州市",
                "兴化市",
                "东台市",
                "常熟市",
                "江阴市",
                "张家港市",
                "通州市",
                "宜兴市",
                "邳州市",
                "海门市",
                "溧阳市",
                "泰兴市",
                "如皋市",
                "昆山市",
                "启东市",
                "江都市",
                "丹阳市",
                "吴江市",
                "靖江市",
                "扬中市",
                "新沂市",
                "仪征市",
                "太仓市",
                "姜堰市",
                "高邮市",
                "金坛市",
                "句容市",
                "灌南县",
                "海安市"
            ],
            "江西省": [
                "南昌市",
                "赣州市",
                "上饶市",
                "宜春市",
                "景德镇市",
                "新余市",
                "九江市",
                "萍乡市",
                "抚州市",
                "鹰潭市",
                "吉安市",
                "丰城市",
                "樟树市",
                "德兴市",
                "瑞金市",
                "井冈山市",
                "高安市",
                "乐平市",
                "南康市",
                "贵溪市",
                "瑞昌市",
                "东乡县",
                "广丰县",
                "信州区",
                "三清山"
            ],
            "辽宁省": [
                "沈阳市",
                "葫芦岛市",
                "大连市",
                "盘锦市",
                "鞍山市",
                "铁岭市",
                "本溪市",
                "丹东市",
                "抚顺市",
                "锦州市",
                "辽阳市",
                "阜新市",
                "调兵山市",
                "朝阳市",
                "海城市",
                "北票市",
                "盖州市",
                "凤城市",
                "庄河市",
                "凌源市",
                "开原市",
                "兴城市",
                "新民市",
                "大石桥市",
                "东港市",
                "北宁市",
                "瓦房店市",
                "普兰店市",
                "凌海市",
                "灯塔市",
                "营口市"
            ],
            "青海省": [
                "西宁市",
                "玉树市",
                "格尔木市",
                "德令哈市"
            ],
            "山东省": [
                "济南市",
                "青岛市",
                "威海市",
                "潍坊市",
                "菏泽市",
                "济宁市",
                "东营市",
                "烟台市",
                "淄博市",
                "枣庄市",
                "泰安市",
                "临沂市",
                "日照市",
                "德州市",
                "聊城市",
                "滨州市",
                "乐陵市",
                "兖州市",
                "诸城市",
                "邹城市",
                "滕州市",
                "肥城市",
                "新泰市",
                "胶州市",
                "胶南市",
                "龙口市",
                "平度市",
                "莱西市"
            ],
            "山西省": [
                "太原市",
                "大同市",
                "阳泉市",
                "长治市",
                "临汾市",
                "晋中市",
                "运城市",
                "忻州市",
                "朔州市",
                "吕梁市",
                "古交市",
                "高平市",
                "永济市",
                "孝义市",
                "侯马市",
                "霍州市",
                "介休市",
                "河津市",
                "汾阳市",
                "原平市",
                "晋城市",
                "潞城市"
            ],
            "陕西省": [
                "西安市",
                "咸阳市",
                "榆林市",
                "宝鸡市",
                "铜川市",
                "渭南市",
                "汉中市",
                "安康市",
                "商洛市",
                "延安市",
                "韩城市",
                "兴平市",
                "华阴市"
            ],
            "四川省": [
                "成都市",
                "广安市",
                "德阳市",
                "乐山市",
                "巴中市",
                "内江市",
                "宜宾市",
                "南充市",
                "都江堰市",
                "自贡市",
                "泸州市",
                "广元市",
                "达州市",
                "资阳市",
                "绵阳市",
                "眉山市",
                "遂宁市",
                "雅安市",
                "阆中市",
                "攀枝花市",
                "广汉市",
                "绵竹市",
                "万源市",
                "华蓥市",
                "江油市",
                "西昌市",
                "彭州市",
                "简阳市",
                "崇州市",
                "什邡市",
                "峨眉山市",
                "邛崃市",
                "双流县"
            ],
            "云南省": [
                "昆明市",
                "玉溪市",
                "大理市",
                "曲靖市",
                "昭通市",
                "保山市",
                "丽江市",
                "临沧市",
                "楚雄市",
                "开远市",
                "个旧市",
                "景洪市",
                "安宁市",
                "宣威市",
                "文山市",
                "普洱市"
            ],
            "浙江省": [
                "杭州市",
                "宁波市",
                "绍兴市",
                "温州市",
                "台州市",
                "湖州市",
                "嘉兴市",
                "金华市",
                "舟山市",
                "衢州市",
                "丽水市",
                "余姚市",
                "乐清市",
                "临海市",
                "温岭市",
                "永康市",
                "瑞安市",
                "慈溪市",
                "义乌市",
                "上虞市",
                "诸暨市",
                "海宁市",
                "桐乡市",
                "兰溪市",
                "龙泉市",
                "建德市",
                "富德市",
                "富阳市",
                "平湖市",
                "东阳市",
                "嵊州市",
                "奉化市",
                "临安市",
                "*市"
            ],
            "*省": [
                "台北市",
                "台南市",
                "台中市",
                "*市",
                "桃源市"
            ],
            "广东省": [
                "广州市",
                "深圳市",
                "珠海市",
                "汕头市",
                "佛山市",
                "韶关市",
                "湛江市",
                "肇庆市",
                "江门市",
                "茂名市",
                "惠州市",
                "梅州市",
                "汕尾市",
                "河源市",
                "阳江市",
                "清远市",
                "东莞市",
                "中山市",
                "潮州市",
                "揭阳市",
                "云浮市"
            ],
            "广西": [
                "南宁市",
                "贺州市",
                "玉林市",
                "桂林市",
                "柳州市",
                "梧州市",
                "北海市",
                "钦州市",
                "百色市",
                "防城港市",
                "贵港市",
                "河池市",
                "崇左市",
                "来宾市",
                "东兴市",
                "桂平市",
                "北流市",
                "岑溪市",
                "合山市",
                "凭祥市",
                "宜州市"
            ],
            "内蒙古": [
                "呼和浩特市",
                "呼伦贝尔市",
                "赤峰市",
                "扎兰屯市",
                "鄂尔多斯市",
                "乌兰察布市",
                "巴彦淖尔市",
                "二连浩特市",
                "霍林郭勒市",
                "包头市",
                "乌海市",
                "阿尔山市",
                "乌兰浩特市",
                "锡林浩特市",
                "根河市",
                "满洲里市",
                "额尔古纳市",
                "牙克石市",
                "临河市",
                "丰镇市",
                "通辽市"
            ],
            "宁夏": [
                "银川市",
                "固原市",
                "石嘴山市",
                "青铜峡市",
                "中卫市",
                "吴忠市",
                "灵武市"
            ],
            "*": [
                "拉萨市",
                "那曲市",
                "山南市",
                "林芝市",
                "昌都市",
                "阿里地区日喀则市"
            ],
            "*": [
                "乌鲁木齐市",
                "石河子市",
                "喀什市",
                "阿勒泰市",
                "阜康市",
                "库尔勒市",
                "阿克苏市",
                "阿拉尔市",
                "哈密市",
                "克拉玛依市",
                "昌吉市",
                "奎屯市",
                "米泉市",
                "和田市",
                "塔城市"
            ],
            "北京": ["北京市"],
            "天津": ["天津市"],
            "上海": ["上海市"],
            "重庆": ["重庆市"],
            "香港": ["香港市"],
            "澳门": ["澳门市"]
        }

api接口开发

这里用的DRF,不会的参考我另一篇文章。

Django Api----djangorestframwork

基础配置不多说,只展示序列化和视图

from blog import models
from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet


class DataModelSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Provence
        fields = ['name', 'value']


class RegionView(ModelViewSet):
    queryset = models.Provence.objects.all()
    serializer_class = DataModelSerializers

models.py

class Provence(models.Model):
    name = models.CharField(max_length=5, verbose_name='省名')
    value = models.IntegerField(default=0, verbose_name='数量', null=True, blank=True)

    def viewed(self):
        """
        增加
        """
        self.value += 1
        self.save(update_fields=['value'])

    class Meta:
        verbose_name = '地域'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

ajax前后端动态交互

<script>
    $.ajax({
        url: "/api/v1/data/",
        type: "get",
        dataType: "json",
        success: function (data) {
            console.log(data);
            var mydata = data
            var optionMap = {
                    backgroundColor: '#FFFFFF',
                    backgroundColor: 'transparent',  // 背景透明色
                    title: {
                        text: '全国来访人员地域分布大数据',
                        subtext: '',
                        x:'center',
                        textStyle:{
                            color: '#CFB53B',
                            fontfamily:'Microsoft YaHei'
                        }
                    },
                    tooltip : {
                        trigger: 'item'
                    },

                    //左侧小导航图标
                    visualMap: {
                        show : false,
                        x: 'left',
                        y: 'center',
                        splitList: [
                            {start: 500, end:600},{start: 400, end: 500},
                            {start: 300, end: 400},{start: 200, end: 300},
                            {start: 100, end: 200},{start: 0, end: 100},
                        ],
                        color: ['#5475f5', '#9feaa5', '#85daef','#74e2ca', '#e6ac53', '#9fb5ea']
                    },

                    //配置属性
                    series: [{
                        name: '数据',
                        type: 'map',
                        mapType: 'china',
                        roam: true,
                        label: {
                            normal: {
                                show: true  //省份名称
                            },
                            emphasis: {
                                show: false
                            }
                        },
                        data:mydata  //数据
                    }]
                };
            //初始化echarts实例
            var myChart = echarts.init(document.getElementById('main'));

            //使用制定的配置项和数据显示图表
            myChart.setOption(optionMap);

        }

    });
</script>
上一篇:centos7.9环境基于docker和pipeline构建jenkins的ci平台


下一篇:.net三层架构开发步骤