1. 程式人生 > >Django使用中介軟體進行流量統計

Django使用中介軟體進行流量統計

為了統計網站訪問流量,計劃做一個訪問資訊統計,
配置:Ubuntu18.4,阿里雲伺服器,已經執行的Django專案(可以現在本地測試),為了便於檢視,本地最好安裝redis desk manager客戶端,客戶端連線雲伺服器流程,可以看另一篇文章:
redis desk manager 遠端連線阿里雲伺服器Redis服務(Ubuntu18.4)
思路:利用Django所有請求都要經過中介軟體的特點,在中介軟體中獲取request.META中的訪問資訊,存入資料庫,考慮到效率,這裡使用了redis資料庫。所以,電腦上需要安裝redis,sudo apt-get install redis-server


流程如下:

1,新建中介軟體檔案

在Django專案目錄下,新建VisitCountMiddleware.py檔案,
定義中介軟體類,
內容如下:

import time
import redis


# 注意類名必須是以Middleware結尾。
class VisitCountMiddleware(object):
    """ 訪問統計 """

    def __init__(self, get_response):
        self.get_response = get_response
        
    def __call__(self, request):
    	# 獲取request屬性,
    	request_meta = request.META
    	response = self.get_response(request)
    	
    	# 對要獲取的引數進行判斷,防止因沒有引數而丟擲異常
    	# ip地址
        if request_meta.get("HTTP_X_FORWARDED_FOR"):
            ip = request_meta["HTTP_X_FORWARDED_FOR"]       
        else:
            ip = request_meta["REMOTE_ADDR"]
        # 起始路徑,可以統計在網站內部的訪問記錄,如:從A到B,起始路徑就是A            
        if request_meta.get('HTTP_REFERER'):
            HTTP_REFERER = request_meta['HTTP_REFERER']
        else:
            HTTP_REFERER = False
       	# 目標路徑,就是上面說到的B
        if request_meta.get('PATH_INFO'):
            PATH_INFO = request_meta['PATH_INFO']
        else:
            PATH_INFO = False
        # User-agent,這一項也可以用來過濾請求
        if request_meta.get('HTTP_USER_AGENT'):
            HTTP_USER_AGENT = request_meta['HTTP_USER_AGENT']
        else:
            HTTP_USER_AGENT = False
	 # 請求方式
        if request_meta.get('REQUEST_METHOD'):
            REQUEST_METHOD = request_meta['REQUEST_METHOD']
        else:
            REQUEST_METHOD = False
	 # 連線方式,
        if request_meta.get('HTTP_CONNECTION'):
            HTTP_CONNECTION = request_meta['HTTP_CONNECTION']
        else:
            HTTP_CONNECTION = False
	 # 響應碼
        response_code = response.status_code
        visit_time = time.strftime("%Y-%m-%d %H:%M:%S")
        # 組裝資料,新增訪問時間visit_time
        info_list = {
                     'IP': ip,
                     'Begin_path': HTTP_REFERER,
                     'End_path': PATH_INFO,
                     'User_agent': HTTP_USER_AGENT,
                     'Request_method': REQUEST_METHOD,
                     'Connection': HTTP_CONNECTION,
                     'Response_code': response_code,
                     'Visit_time': visit_time
                     }
                   
        # 呼叫儲存資料庫函式,存入資料庫 
        self.save_to_redis(info_list)
        return response

2,定義資料庫函式

由於redis是NoSQL,是以鍵值對方式儲存資訊的,所以,每一條訪問記錄,都要給它一個鍵,我這裡使用關鍵字+數字做為鍵名,為了避免頻繁的想資料庫發起連線請求,這裡使用連線池,

# 連線池放到VisitCountMiddleware類外面,
pool = redis.ConnectionPool(host='127.0.0.1', password='密碼', port=6379, db=0)
	# 函式放到VisitCountMiddleware內部,
    def save_to_redis(self, result):
        """
        儲存至Redis資料庫
        :param result: type: dict
        :return: 
        """
        # 資料庫鍵名編號num,也是訪問次數,從1開始
        num = 0
        # 連線資料庫,try一下,捕獲異常
        try:
            conn = redis.Redis(connection_pool=pool)
            # 在資料庫中有訪問次數,就是用資料庫中的,如果沒有(第一次),就使用上面的num=0,
            if conn.get('number'):
            	# 因為redis資料庫中鍵值對的值是以str型別儲存的,下面需要進行加操作,因此需要轉換成int
                num = int(conn.get('number')),
        except ConnectionError as e:
            print(e, '連線redis資料庫失敗')
        # 儲存資料
        try:
            num += 1            
            # 這裡使用format動態建立鍵名,因為result是字典,所有,儲存資料庫時使用Hash資料型別, 
            conn.hmset('visit_info{}'.format(num), result)               
            # 如果資料儲存如資料庫,再把num存入資料庫,鍵名為‘number’
            conn.set('number', num)
            print('成功存入redis資料庫')
        except Exception as e:
            print(e, '儲存redis資料庫失敗')

這裡還可以統計固定時間內,同一IP的訪問次數,比如1分鐘內同一ip的訪問量,可以用來過濾爬蟲等非正常訪問。不過這不是本次的目的,下次再說。

3,配置生效

把中介軟體新增到Django專案setting內MIDDLEWARE列表內,這裡要注意路徑,比如我們的中介軟體檔案是放在專案根目錄下,檔名 VisitCountMiddleware.py,類名VisitCountMiddleware,就新增 "VisitCountMiddleware.VisitCountMiddleware",如果在別的資料夾,就要把路徑加上。

4,效果圖:

在這裡插入圖片描述
如果沒有安裝redis desk manager,就在雲伺服器檢視,遠端登入雲伺服器,redis-cli啟動redis,(如有密碼,需要輸入密碼驗證:auth 密碼),我們儲存在0號庫,啟動redis後,預設進入0庫,不需要另行選擇,如果存在別的庫(連線池中的db選項),使用select 庫名,切換庫,keys * 檢視庫中的所有鍵名,查詢一個鍵名內的所有資訊,用hgetall 鍵名。檢視單個鍵的一個屬性用hget 鍵名 加資料字典的鍵名,如我們檢視第38條訪問的ip資訊,命令就是 hget visit_info38 IP 如圖
在這裡插入圖片描述