Django使用中间件进行流量统计

版权声明:本文为博主原创文章,转载请联系作者获得授权并注明出处。 https://blog.csdn.net/qq_34172340/article/details/84559874

为了统计网站访问流量,计划做一个访问信息统计,
配置: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 如图
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34172340/article/details/84559874