不为成仙,只为在这红尘中等你回来。

您现在的位置是:网站首页>>Django

Django 统计网站访问次数、访问 ip 、访问端点及次数

2018年12月3日 18:19 | 分类:Django | 标签: Django

有时候写完博客,想知道网站每天的访问量,都有哪些人访问,都是来自什么地方的访客,都访问了哪些端点。

效果如下:

编写 blog/models.py

# 访问网站的 ip 地址、端点和次数
class UserIP(models.Model):
    ip = models.CharField(verbose_name='IP 地址', max_length=30)
    ip_addr = models.CharField(verbose_name='IP 地理位置', max_length=30)
    end_point = models.CharField(verbose_name='访问端点', default='/', max_length=30)
    count = models.IntegerField(verbose_name='访问次数', default=0)

    class Meta:
        verbose_name = '访问用户信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.ip

# 网站总访问次数
class VisitNumber(models.Model):
    count = models.IntegerField(verbose_name='网站访问总次数', default=0) # 网站访问总次数

    class Meta:
        verbose_name = '网站访问总次数'
        verbose_name_plural = verbose_name

    def __str__(self):
        return str(self.count)

# 单日访问量统计
class DayNumber(models.Model):
    day = models.DateField(verbose_name='日期', default=timezone.now)
    count = models.IntegerField(verbose_name='网站访问次数', default=0) # 网站访问总次数

    class Meta:
        verbose_name = '网站日访问量统计'
        verbose_name_plural = verbose_name

    def __str__(self):
        return str(self.day)

使用 geoip2 实现 IP 转换成现实地理位置

安装 geoip2 库

pip install geoip2

下载 Maxmind 网站的 IP 信息库

地址:http://dev.maxmind.com/geoip/geoip2/geolite2

下载完之后,解压,将解压包中的 mmdb 文件复制到项目的应用程序中 (我的网站是 ‘blog’)。项目结构如下图所示:

编写将 IP 转换为现实地理位置的函数

blog/ip_convert_addr.py

import geoip2.database


def ip_to_addr(ip):
    """
    IP 转换成现实中的地理位置
    country = 国家
    province = 省
    city = 城市
    """
    reader = geoip2.database.Reader('blog/GeoLite2-City.mmdb')
    response = reader.city(ip)
    #print(response)
    # 因为有些IP的省份和城市未知,所以设置默认为空
    province = ''
    city = ''
    try:
        # 国家、省份、城市
        country = response.country.names["zh-CN"]
        province = response.subdivisions.most_specific.names["zh-CN"]
        city = response.city.names["zh-CN"]
    except:
        pass
    if country != '中国':
        return country
    if province and city:
        if province == city or city in province:
            return province
        return '%s%s' %(province, city)
    elif province and not city:
        return province
    else:
        return country

参考:Python获取IP的地理位置:经纬度,国家,区域,城市

编写 blog/visit_info.py 实现更新网站访问量和访问 ip 等信息

from django.utils import timezone

from .models import UserIP, VisitNumber, DayNumber
from .ip_convert_addr import ip_to_addr


# 自定义的函数,不是视图
def change_info(request, end_point):
    """
    # 修改网站访问量和访问 ip 等信息
    # 每一次访问,网站总访问次数加一
    """
    count_nums = VisitNumber.objects.filter(id=1)
    if count_nums:
        count_nums = count_nums[0]
        count_nums.count += 1
    else:
        count_nums = VisitNumber()
        count_nums.count = 1
    count_nums.save()

    # 记录访问 ip 和每个 ip 的次数
    if 'HTTP_X_FORWARDED_FOR' in request.META:  # 获取 ip
        client_ip = request.META['HTTP_X_FORWARDED_FOR']
        client_ip = client_ip.split(",")[0]  # 所以这里是真实的 ip
    else:
        client_ip = request.META['REMOTE_ADDR']  # 这里获得代理 ip
    # print(client_ip)

    ip_exist = UserIP.objects.filter(ip=str(client_ip), end_point=end_point)
    if ip_exist:  # 判断是否存在该 ip
        uobj = ip_exist[0]
        uobj.count += 1
    else:
        uobj = UserIP()
        uobj.ip = client_ip
        uobj.end_point = end_point
        try:
            uobj.ip_addr = ip_to_addr(client_ip)
        except:
            uobj.ip_addr = 'unknown'
        uobj.count = 1
    uobj.save()

    # 增加今日访问次数
    date = timezone.now().date()
    today = DayNumber.objects.filter(day=date)
    if today:
        temp = today[0]
        temp.count += 1
    else:
        temp = DayNumber()
        temp.dayTime = date
        temp.count = 1
    temp.save()

将上面的函数导入到视图中,在需要时直接调用

blog/view.py

...
from .visit_info import change_info


...
def post_detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    post.yueduliang()
    change_info(request, '/')
    # 记得在顶部引入 markdown 模块
    post.body = markdown.markdown(post.body, extensions=['extra', 'codehilite', 'toc',
                                    'tables', 'sane_lists'])
    return render(request, 'post_detail.html', context={'post': post})

数据库迁移

因为我们在 models.py 中创建了 3 个新类,所以需要执行以下命令,以使之作用于数据库。

$ python manage.py makemigrations
$ python manage.py migrate

之后重启下服务器,这样一个最简单的页面访问量统计就完成了。

参考

django统计网站访问次数,同时记录访问ip地址和次数
Python获取IP的地理位置:经纬度,国家,区域,城市