像電影裡的黑客一樣工作:IP數據可視化,學完當場就能撩妹

前言

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

下面是效果圖,由於數據量有限,所以還不夠眼花繚亂.

像電影裡的黑客一樣工作:IP數據可視化,學完當場就能撩妹

像電影裡的黑客一樣工作:IP數據可視化,學完當場就能撩妹

本文的主要內容是通過echarts,threejs將web日誌或者任何含有IP數據的文本文件可視化.簡單的來說,裝逼,可以將這個動態圖放在大屏幕上.

所有源碼及相關數據文件請訪問下面github倉庫

https://github.com/youerning/blog/tree/master/ip-visualize

前提條件

  • 熟悉python及框架flask

  • 熟悉JavaScript

獲取數據

IP數據

數據獲取方式

  • 日誌文件

  • elk三件套

  • 其他

歸根結底數據最終來自日誌文件, 這裡主要指web日誌。

這裡使用我自己網站的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'

通過下面代碼將IP地址拿出來.

# 打開日誌文件fp = open("website.log")# 創建ip集合,由於這裡只需要IP地址,所以用集合的特性去重ip_set = set()# 通過循環每次讀取日誌一行,如果日誌量大建議以下方式,日誌文件不大,可以直接readlines,一次性全部讀取出來,while True: line = fp.readline() if len(line.strip()) < 1: break ip = line.split()[0] ip_set.add(ip)# 訪問用戶IP的個數len(ip_set)# 查看前20個IPlist(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']不過為了使用廣泛這裡使用正則表達式.import repat = "\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)下面是完整步驟 # 創建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: # 通過循環每次讀取日誌一行,如果日誌量大建議以下方式,日誌文件不大,可以直接readlines,一次性全部讀取出來 # 如果太大則用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)

至此,我們將訪問文件裡面的的IP拿出來了。

值得注意的是: 如果你有搭建elk之類的日誌集群,那麼獲取數據會更簡單更快,只是方式不同而已.這裡就不贅述了.

IP地址的地理信息

如果只是拿到IP數據,在本文並沒有用,因為為了在地圖上可視化每一個IP的位置,我們需要知道每個IP地址的地理信息,即,經緯度,所在城市等。

這裡使用dev.maxmind.com提供的開源免費的geoip數據庫.

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

這裡不保證IP地址對應的位置信息絕對正確。為了保證IP地址的準確性,可以搜索在線的Geo服務。

為了使用上面下載的數據庫,首先得下載相應的模塊.

pip install geoip2

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

# 導入相應模塊import geoip2.database# 記載下載的數據庫文件路徑,這裡是在代碼執行的工作目錄reader = geoip2.database.Reader("GeoLite2-City.mmdb")response = reader.city("61.141.65.76")# 查看國家名response.country.nameOut[115]: 'China'# 查看城市名response.city.nameOut[116]: 'Shenzhen'response.city.names["zh-CN"]Out[117]: '深圳市'# 查看經緯度response.location.latitudeOut[118]: 22.5333response.location.longitudeOut[119]: 114.1333

上面只是用geoip2這個庫查看城市,國家, 經緯度,更多信息可自己探索.

處理數據

在處理數據之前,我們要知道,我們要處理成什麼數據格式,由於畫圖是一件很費時費力的工作,這裡藉助的是這個echarts的demo,地址如下:

http://echarts.baidu.com/examples/editor.html?c=lines3d-flights&gl=1

該demo的數據源如下:

http://echarts.baidu.com/examples/data-gl/asset/data/flights.json

數據結構大致如下。

像電影裡的黑客一樣工作:IP數據可視化,學完當場就能撩妹

但是這個格式實在是有點讓人誤導

通過閱讀demo的js代碼,你會發現,繪製飛線的數據格式為:

[[[源緯度數據點, 源經度數據點], [目標維度數據點, 目標經度數據點]]..]

而threejs所需的數據格式號如下

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

關於echarts官網demo的解讀可以在下面地址查看.

https://github.com/youerning/blog/blob/master/ip-visualize/ipvis/prototype/lines3d-flights.html

代碼插入太多太佔篇幅。

數據處理如下

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]

可視化數據

在處理完數據之後就可以通過一個接口暴露數據,這裡使用json數據格式.

然後通過ajax獲取數據.

數據實時更新

這裡只說思路

  • 日誌文件

    主要是通過python的文件對象的文件位置作為數據是否有新內容寫入,如果有就讀入,加載數據到暴露的數據接口

  • elk stack

    這個就比較簡單了,定時查詢數據

demo使用教程

#安裝依賴pip install flask, geoip2# 下載源代碼# 進入到ipvis目錄# 將含有日誌文件放到logs目錄下# 啟動python app.py# 訪問webhttp://127.0.0.1/p1http://127.0.0.1/p2

值得注意的是geoip自定義的數據庫查詢並不是非常的快,所以當你訪問頁面的時候會感覺比較慢,主要是ip數據的查詢耗時太久, 1.8w條數據大概查詢14秒左右

還有就是echarts這個庫可能有性能問題(至少是這個球形圖的時候,即時是官方網站的官方demo),因為當你打開http://127.0.0.1/p1的時候,可能cpu飆升到100%

不足之處

  • 不能實時加載數據

  • 數據量過大有性能問題

  • IP數據分類不夠細化

  • 圖表不夠健全

總結

一個僅僅於我而言有意思的小項目。不確定你們有沒有更多的有意思的想法.


分享到:


相關文章: