为了统计网站访问流量,计划做一个访问信息统计,
配置: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
如图