溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

面子工程之IP數(shù)據(jù)可視化

發(fā)布時(shí)間:2020-08-02 07:25:31 來(lái)源:網(wǎng)絡(luò) 閱讀:28908 作者:youerning 欄目:大數(shù)據(jù)

前言

我很在意的一件事情是好看,嗯,好看.以及是否有趣.雖然不一定有用.

下面是效果圖,由于數(shù)據(jù)量有限,所以還不夠眼花繚亂.

面子工程之IP數(shù)據(jù)可視化

面子工程之IP數(shù)據(jù)可視化

本文的主要內(nèi)容是通過(guò)echarts,threejs將web日志或者任何含有IP數(shù)據(jù)的文本文件可視化.簡(jiǎn)單的來(lái)說(shuō),裝逼,可以將這個(gè)動(dòng)態(tài)圖放在大屏幕上.

所有源碼及相關(guān)數(shù)據(jù)文件請(qǐng)?jiān)L問(wèn)下面github倉(cāng)庫(kù)
https://github.com/youerning/blog/tree/master/ip-visualize

前提條件

  • 熟悉python及框架flask
  • 熟悉JavaScript

獲取數(shù)據(jù)

IP數(shù)據(jù)

數(shù)據(jù)獲取方式

  • 日志文件
  • elk三件套
  • 其他

歸根結(jié)底數(shù)據(jù)最終來(lái)自日志文件, 這里主要指web日志。

這里使用我自己網(wǎng)站的web日志,格式如下.

'116.24.64.239 - - [12/Mar/2018:18:58:40 +0800] "GET /example HTTP/2.0" 502 365\n'
...
'116.24.64.239 - - [12/Mar/2018:18:54:55 +0800] "GET / HTTP/2.0" 200 1603\n'

通過(guò)下面代碼將IP地址拿出來(lái).

# 打開日志文件
fp = open("website.log")

# 創(chuàng)建ip集合,由于這里只需要IP地址,所以用集合的特性去重
ip_set = set()

# 通過(guò)循環(huán)每次讀取日志一行,如果日志量大建議以下方式,日志文件不大,可以直接readlines,一次性全部讀取出來(lái),
while True:
    line = fp.readline()
    if len(line.strip()) < 1:
        break
    ip = line.split()[0]
    ip_set.add(ip)

# 訪問(wèn)用戶IP的個(gè)數(shù)
len(ip_set)

# 查看前20個(gè)IP
list(ip_set)[:20]
['111.206.36.133',
 '220.181.108.183',
 '40.77.178.63',
 '220.181.108.146',
 '119.147.207.152',
 '112.97.63.49',
 '66.249.64.16',
 '138.246.253.19',
 '123.125.67.164',
 '40.77.179.59',
 '66.249.69.170',
 '119.147.207.144',
 '66.249.79.108',
 '157.55.39.23',
 '123.125.71.80',
 '42.236.10.84',
 '123.125.71.79',
 '111.206.36.10',
 '106.11.152.155',
 '66.249.66.148']

不過(guò)為了使用廣泛這里使用正則表達(dá)式.
import re
pat = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
ipfind = re.compile(pat)

line = '116.24.64.239 - - [12/Mar/2018:18:54:55 +0800] "GET / HTTP/2.0" 200 1603\n'

ip = ipfind.findall(line)
if ip:
    ip = ip[0]
    print(ip)

下面是完整步驟
    # 創(chuàng)建ip列表
    ip_lis = list()

    # files of logs
    files = glob("logs/*")

    # complie regex
    pat = "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
    ipfind = re.compile(pat)

    # extract ip from  every file
    for logfile in files:
        with open(logfile) as fp:
            # 通過(guò)循環(huán)每次讀取日志一行,如果日志量大建議以下方式,日志文件不大,可以直接readlines,一次性全部讀取出來(lái)
            # 如果太大則用readline一行一行的讀

            lines = fp.readlines()
            for line in lines:
                if len(line.strip()) < 1:
                    continue
                ip = ipfind.findall(line)
                if ip:
                    ip = ip[0]
                    ip_lis.append(ip)

至此,我們將訪問(wèn)文件里面的的IP拿出來(lái)了。

值得注意的是: 如果你有搭建elk之類的日志集群,那么獲取數(shù)據(jù)會(huì)更簡(jiǎn)單更快,只是方式不同而已.這里就不贅述了.

IP地址的地理信息

如果只是拿到IP數(shù)據(jù),在本文并沒(méi)有用,因?yàn)闉榱嗽诘貓D上可視化每一個(gè)IP的位置,我們需要知道每個(gè)IP地址的地理信息,即,經(jīng)緯度,所在城市等。

這里使用dev.maxmind.com提供的開源免費(fèi)的geoip數(shù)據(jù)庫(kù).

下載地址: https://dev.maxmind.com/geoip/geoip2/geolite2/

這里不保證IP地址對(duì)應(yīng)的位置信息絕對(duì)正確。為了保證IP地址的準(zhǔn)確性,可以搜索在線的Geo服務(wù)。

為了使用上面下載的數(shù)據(jù)庫(kù),首先得下載相應(yīng)的模塊.

pip install geoip2

通過(guò)下面代碼獲取指定IP的地理信息

# 導(dǎo)入相應(yīng)模塊
import geoip2.database

# 記載下載的數(shù)據(jù)庫(kù)文件路徑,這里是在代碼執(zhí)行的工作目錄
reader = geoip2.database.Reader("GeoLite2-City.mmdb")

response = reader.city("61.141.65.76")

# 查看國(guó)家名
response.country.name
Out[115]: 'China'

# 查看城市名
response.city.name
Out[116]: 'Shenzhen'

response.city.names["zh-CN"]
Out[117]: '深圳市'

# 查看經(jīng)緯度
response.location.latitude
Out[118]: 22.5333

response.location.longitude
Out[119]: 114.1333

上面只是用geoip2這個(gè)庫(kù)查看城市,國(guó)家, 經(jīng)緯度,更多信息可自己探索.

處理數(shù)據(jù)

在處理數(shù)據(jù)之前,我們要知道,我們要處理成什么數(shù)據(jù)格式,由于畫圖是一件很費(fèi)時(shí)費(fèi)力的工作,這里借助的是這個(gè)echarts的demo,地址如下:
http://echarts.baidu.com/examples/editor.html?c=lines3d-flights&gl=1

該demo的數(shù)據(jù)源如下:
http://echarts.baidu.com/examples/data-gl/asset/data/flights.json

數(shù)據(jù)結(jié)構(gòu)大致如下。

面子工程之IP數(shù)據(jù)可視化

但是這個(gè)格式實(shí)在是有點(diǎn)讓人誤導(dǎo)
通過(guò)閱讀demo的js代碼,你會(huì)發(fā)現(xiàn),繪制飛線的數(shù)據(jù)格式為:
[[[源緯度數(shù)據(jù)點(diǎn), 源經(jīng)度數(shù)據(jù)點(diǎn)], [目標(biāo)維度數(shù)據(jù)點(diǎn), 目標(biāo)經(jīng)度數(shù)據(jù)點(diǎn)]]..]

而threejs所需的數(shù)據(jù)格式號(hào)如下

var data = [
    [
    'seriesA', [ latitude, longitude, magnitude, latitude, longitude, magnitude, ... ]
    ],
    [
    'seriesB', [ latitude, longitude, magnitude, latitude, longitude, magnitude, ... ]
    ]
];

關(guān)于echarts官網(wǎng)demo的解讀可以在下面地址查看.
https://github.com/youerning/blog/blob/master/ip-visualize/ipvis/prototype/lines3d-flights.html

代碼插入太多太占篇幅。

數(shù)據(jù)處理如下

from functools import lru_cache

@lru_cache(maxsize=512)
def get_info(ip):
    """
    return info of ip

    Returns:
        city, country, sourceCoord, destCoord
    """
    try:
        resp = reader.city(ip)
        city = resp.city.name
        if not city:
            city = "unknow"
        country = resp.country.names["zh-CN"]
        if not country:
            country = "unknow"
    except Exception as e:
        print("the ip is bad: {}".format(ip))
        print("=" * 30)
        print(e)
        return False

    sourceCoord = [resp.location.longitude, resp.location.latitude]
    return city, country, sourceCoord, destCoord

# ip_Lis為上面獲取的IP地址列表
ipinfo_lis = [get_info(ip) for ip in ip_lis]

可視化數(shù)據(jù)

在處理完數(shù)據(jù)之后就可以通過(guò)一個(gè)接口暴露數(shù)據(jù),這里使用json數(shù)據(jù)格式.
然后通過(guò)ajax獲取數(shù)據(jù).

數(shù)據(jù)實(shí)時(shí)更新

這里只說(shuō)思路

  • 日志文件

    主要是通過(guò)python的文件對(duì)象的文件位置作為數(shù)據(jù)是否有新內(nèi)容寫入,如果有就讀入,加載數(shù)據(jù)到暴露的數(shù)據(jù)接口

  • elk stack
    這個(gè)就比較簡(jiǎn)單了,定時(shí)查詢數(shù)據(jù)

demo使用教程

#安裝依賴
pip install flask, geoip2

# 下載源代碼

# 進(jìn)入到ipvis目錄

# 將含有日志文件放到logs目錄下
# 啟動(dòng)
python app.py

# 訪問(wèn)web
http://127.0.0.1/p1
http://127.0.0.1/p2

值得注意的是geoip自定義的數(shù)據(jù)庫(kù)查詢并不是非常的快,所以當(dāng)你訪問(wèn)頁(yè)面的時(shí)候會(huì)感覺(jué)比較慢,主要是ip數(shù)據(jù)的查詢耗時(shí)太久, 1.8w條數(shù)據(jù)大概查詢14秒左右

還有就是echarts這個(gè)庫(kù)可能有性能問(wèn)題(至少是這個(gè)球形圖的時(shí)候,即時(shí)是官方網(wǎng)站的官方demo),因?yàn)楫?dāng)你打開http://127.0.0.1/p1的時(shí)候,可能cpu飆升到100%

不足之處

  • 不能實(shí)時(shí)加載數(shù)據(jù)
  • 數(shù)據(jù)量過(guò)大有性能問(wèn)題
  • IP數(shù)據(jù)分類不夠細(xì)化
  • 圖表不夠健全

總結(jié)

一個(gè)僅僅于我而言有意思的小項(xiàng)目。不確定你們有沒(méi)有更多的有意思的想法.

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI