思路,通過python執行shell命令,截取nginx日誌第一列,即用戶來源ip,寫入到mysql中。
通過埃文科技的ip地址庫,查詢ip對應的省份,再寫入mysql中。
通過echarts繪製到地圖中,實現用戶來源可視化。
第一步:
首先創建表結構:
CREATE TABLE `access` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ip` varchar(100) DEFAULT NULL,
`count` int(10) DEFAULT NULL,
`province` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
第二步:
python代碼:
#!/usr/bin/python
#coding=utf-8
import os
import mysql.connector
# nginx日誌路徑
file_path = "/root/access.log"
# ip排序+統計個數並去重
data = os.popen("cat access.log | awk '{print$1}' | sort | uniq -c")
array_data = {}
array_data_value = 0
for i in data:
i = i.strip()
array_data[array_data_value] = i.split(' ')
array_data_value = array_data_value + 1
# 數據庫連接,庫名simon
db = mysql.connector.connect(host='192.168.10.105', user='root', password='root', database='simon', charset='utf8')
cursor = db.cursor(dictionary=True)
########################## 插入操作 ##############################
for x in array_data:
#print array_data[x]
try:
# 我的表名叫access
cursor.execute("INSERT INTO `access` (`ip`,`count`) VALUES (%s,%s);",(str(array_data[x][1]),str(array_data[x][0])))
print "數據id:" + str(cursor.lastrowid)
except Exception,e:
print "插入失敗,錯誤類型: " + str(Exception) + "錯誤原因: " + str(e)
# 關閉連接
cursor.close()
db.commit() # 插入數據必用,否則不提交到mysql
db.close()
第三步:
從 https://mall.ipplus360.com/product/detail?productId=5 下載埃文科技的ip地址庫。根據其提供的手冊,導入到mysql中。
第四步:
下載echarts圖表 http://echarts.baidu.com/demo.html#map-labels ,我這裡通過公司的前端同事協助下載。
第五步,更新省份:
用php處理數據,之前py插入的數據只有ip,訪問次數,沒有ip對應的省份。這裡我用php處理。
方法就是通過埃文科技的地址庫,查出來對應省份,再去更新表。由於php框架眾多,寫法也不太一樣,下面的php代碼供大家參考。
// 查詢ip地址
$rs = $db -> prepare("SELECT `ip` FROM `access`;") -> execute();
// 循環查詢ip對應省份
foreach ($rs as $v)
{
$location = $db -> prepare("SELECT `multiarea` FROM `aiwen_free_district_v2.0.1` WHERE INET_ATON(:ip) BETWEEN `minip` AND `maxip` LIMIT 0,1;")
-> execute(array(':ip'=>$v['ip']));
$location = json_decode($location[0]['multiarea'], true);
$province = $location[0]['p'] ? $location[0]['p'] : '未知'; // ip地址庫不一定能查到ip的省份,為了冗餘,查不到的時候賦值為 未知
// 更新省份字段
$rs = $db -> prepare("UPDATE `access` SET `province` = :province WHERE `ip` = :ip;") -> execute(array(':province'=>$province, ':ip'=>$v['ip']));
}
第六步,繪製圖表:
php代碼,僅供參考。
$db = db::init();
$rs = $db -> prepare("SELECT SUM(`count`) AS `count`,`province` FROM `access` WHERE `province` != '未知' AND `province` IS NOT NULL GROUP BY `province`;") -> execute();
$list = array();
foreach ($rs as $k => $v)
{
// 這裡是因為echarts出來的數據不帶“省”“自治區”,所以要去掉,否則圖表出不來數據。
$list[$k]['count'] = $v['count'];
$p = str_replace('省', '', $v['province']);
$p = str_replace('自治區', '', $p);
$list[$k]['province'] = $p;
}
template::assign('list', $list);
template::display('index');
然後對html頁面賦值。
如圖。
最終效果圖: