目录

统计进行的背景

统计的构思

统计的代码实现


  • 需求背景

    不接入第三方系统的情况下,本系统进行以下数据的统计。每个Mac地址算一个独立访客。IP 不能算独立访客,同一个局域网对外属于一个IP。未找到合适在php7+ 版本的 去除代理等 获取真实IP的方式。

更新于2018年9月1日:本文的获取Mac 地址放到服务器测试获取不到访问者的MAC,UV 最后使用还是访问的 IP 数。希望有可以获取到访问者Mac地址的小伙伴不吝赐教。

  1. 访问PV
  2. 访问UV
  3. 独立IP
  4. 页面访问时长
  5. 人均页面访问数
  • 统计的构思

    laravel 版本 5.6 + Redis + JS 埋点

  • 统计的代码实现

JS 代码实现,统计页面访问时长,及是否跳出

    var current = Date.parse(new Date())/1000;var url = self.location.href; // 获取用户当前访问页面var out_num;var page_view_long = 0;var endMytime = current+30*60; // 计算过期时间戳window.onload = function () {//$.cookie('statistics',null);out_num = $.cookie('statistics');if (isNaN(out_num)||out_num==null){console.log('if');out_num = $.cookie("statistics",0,{expires:endMytime});}else{// $.cookie("statistics",out_num);out_num++;console.log('else',out_num);$.cookie("statistics",out_num,{expires:endMytime});}}();window.addEventListener('beforeunload', logData, false);function logData() {var end = Date.parse(new Date())/1000;out_num = $.cookie('statistics');page_view_long = end-current;if (out_num>=1){out = 0}else{out = 1;}$.cookie("statistics",out_num);// window.navigator.sendBeacon("/statistics", 'id=xxx&s=2&_token='+csrf_token);var client = new XMLHttpRequest();client.open("POST", "/statistics", false); // 第三个参数表明是同步的 xhrclient.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");client.send('url='+url+'&_token='+csrf_token+'&out='+out+'&page_view_long='+page_view_long+'&current='+current+'&out_num='+out_num);}

中间件 记录了所有请求的记录。js 的记录不包括AJAX 和 FORM 表单提交。具体要存储的信息在中间件存入redis 队列即可。

代码根据自己的需求写,如些列举一些常用函数。

<?php
/*** Created by Engineer CuiCui.* Project: deal.* Date: 2018/8/21-14:56*/
namespace App\Http\Middleware;use Illuminate\Support\Facades\Redis;
use Closure;class WebStatistics
{public $return_array=[];// 返回带有MAC地址的字串数组public $mac_addr;/*** Handle an incoming request.** @param  \Illuminate\Http\Request  $request* @param  \Closure  $next* @param  string|null  $guard* @return mixed*/public function handle($request, Closure $next, $guard = null){if (config('app.statistics')==true) { // 此处可以不定义配置开关。// 自主获取需要存储的数组。redisLine = ['pv'=>'data',...];Redis::lpush('WebStatistics', json_encode($redisLine, JSON_UNESCAPED_UNICODE));return $next($request);}else{return $next($request);}}/*** Handle an incoming request ip addr.** @TODO 获取用户IP地址* @param  string|null* @return string* */private function getIp(){if(!empty($_SERVER["HTTP_CLIENT_IP"])){$cip = $_SERVER["HTTP_CLIENT_IP"];}else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])){$cip = $_SERVER["HTTP_X_FORWARDED_FOR"];}else if(!empty($_SERVER["REMOTE_ADDR"])){$cip = $_SERVER["REMOTE_ADDR"];}else{$cip = '';}preg_match("/[\d\.]{7,15}/", $cip, $cips);$cip = isset($cips[0]) ? $cips[0] : 'unknown';unset($cips);return $cip;}/*** @TODO 获得访问者浏览器* @return string*/private function browseInfo() {if (!empty($_SERVER['HTTP_USER_AGENT'])) {$br = $_SERVER['HTTP_USER_AGENT'];if (preg_match('/MSIE/i', $br)) {$br = 'MSIE';} else if (preg_match('/Firefox/i', $br)) {$br = 'Firefox';} else if (preg_match('/Chrome/i', $br)) {$br = 'Chrome';} else if (preg_match('/Safari/i', $br)) {$br = 'Safari';} else if (preg_match('/Opera/i', $br)) {$br = 'Opera';} else {$br = 'Other';}return $br;} else {return 'unknow';}}function GetMacAddr($os_type){switch ( strtolower($os_type) ){case "linux":self::forLinux();break;case "solaris":break;case "unix":break;case "aix":break;default:self::forWindows();break;}$temp_array = array();foreach ( $this->return_array as $value ){if (preg_match("/[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f]/i",$value,$temp_array ) ){$this->mac_addr = $temp_array[0];break;}}unset($temp_array);return $this->mac_addr;}function forWindows(){@exec("ipconfig /all", $this->return_array);if ( $this->return_array )return $this->return_array;else{$ipconfig = $_SERVER["WINDIR"]."\system32\ipconfig.exe";if ( is_file($ipconfig) )@exec($ipconfig." /all", $this->return_array);else@exec($_SERVER["WINDIR"]."\system\ipconfig.exe /all", $this->return_array);return $this->return_array;}}function forLinux(){@exec("ifconfig -a", $this->return_array);return $this->return_array;}
}

定时任务 ,根据存储的 Redis,进行出队。Redis 无回滚功能。如果出队的数据不符合存储条件可继续入队。不会影响本次出队的循环。Redis 出队循环示例:

/*** Execute the console command.** @return mixed*/public function handle(){$current   = time();$count     = Redis::LLEN('WebStatistics');$redisList = Redis::lrange('WebStatistics',0,$count);// dd($redisList);// TODO 埋点统计 访问页面的信息,每小时即出队清空一次 redis 数据 WebStatistics 。array_walk($redisList,function($value,$key){// 每次循环初始化$lpop = '';$create=false;$saveParams=[];$lpop = Redis::rpop('WebStatistics');$saveParams = json_decode($lpop,1);});}

知识点学习

前端全(无)埋点之页面停留时长统计

关于页面停留时间

【百度统计】“跳出率”是如何统计的?为什么我的网站跳出率这么高?

独立访客数UV、访问量PV和IP数的区别

js记录用户在网站的浏览记录和停留时间

Laravel 页面 PV 统计实例相关推荐

  1. 高性能Redis实战 - 实战入门篇 - 基于 Redis 实现 Laravel 全站访问 PV 统计中间件功能

    1.应用场景 主要用于学习Redis缓存使用,以及如何基于Lavavel(中间件)现实全站PV统计, 触类旁通,其他框架或者功能实现是一样的道理,只是代码实现起来,会有差别- 2.学习/操作 1.文档 ...

  2. 从零开始搭建自己的网站二十一:网站IP/PV统计功能设计

    这里先介绍几个概念 IP: 指独立IP数.00:00-24:00内相同IP地址之被计算一次. PV:即Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次. UV: 即Unique V ...

  3. 【作业】组合数据类型练习,英文词频统计实例

    1.列表实例:由字符串创建一个作业评分列表,做增删改查询统计遍历操作.例如,查询第一个3分的下标,统计1分的同学有多少个,3分的同学有多少个等. 1 score = list('012332211') ...

  4. java统计多个线程的请求次数_Web并发页面访问量统计实现

    页面访问量统计,可能在上学的时候就讲过如何简单实现,例如在servletContext中保存一个页页面访问次数,然后每访问一次加1:或者每访问一次就把操作记录保存到数据库,这样的处理方式,做做实验就算 ...

  5. 组合数据类型练习,英文词频统计实例9-21

    1.列表实例:由字符串创建一个作业评分列表,做增删改查询统计遍历操作.例如,查询第一个3分的下标,统计1分的同学有多少个,3分的同学有多少个等. >>>score=list('212 ...

  6. python字频统计软件_python结巴分词以及词频统计实例

    python结巴分词以及词频统计实例 发布时间:2018-03-20 14:52, 浏览次数:773 , 标签: python # coding=utf-8 ''' Created on 2018年3 ...

  7. python爬虫实例手机_Python爬虫实现爬取京东手机页面的图片(实例代码)

    实例如下所示: __author__ = 'Fred Zhao' import requests from bs4 import BeautifulSoup import os from urllib ...

  8. 组合数据类型练习,英文词频统计实例上(2017.9.22)

    字典实例:建立学生学号成绩字典,做增删改查遍历操作. sno=['33号','34号','35号','36号'] grade=[100,90,80,120] d={'33号':100,'34号':90 ...

  9. 简述php和web交互过程,PHP与Web页面交互操作实例分析

    PHP与Web页面交互操作实例分析,表单,数组,参数,字符串,属性 PHP与Web页面交互操作实例分析 易采站长站,站长之家为您整理了PHP与Web页面交互操作实例分析的相关内容. 本文实例讲述了PH ...

最新文章

  1. python http接口_python实现http接口测试
  2. 链mysql_mysql 版本链机制 readView
  3. v-model双向绑定原理_Vue数据绑定
  4. c++ file* 句柄泄漏_C++核心准则?讨论:持有没有被句柄管理的资源时切勿抛出异常...
  5. 计算机跨考医学检验技术,医学检验技术考研可以考哪些专业?
  6. selinux= 为 disabled_「丁香园」五年没考过执医,就不要出来「为祸人间」了
  7. openshift for linux
  8. 给所有准备考网络工程师的考生的一点点建议
  9. 阿里部署edas,采用hsf框架,启动项目时无法启动的问题。
  10. Zotero——下载知网PDF文件
  11. 植物大战僵尸辅助之重叠植物
  12. 微电影|小白创作微电影的辛酸
  13. IPQ6000 WIFI6无线配置和启动过程
  14. 成百家之言,纳万端思辨,SDCC 2017·深圳站响号以待
  15. Docker管理工具Web UI:DockerUI Shipyard /portainer
  16. Redis学习(三)redis的持久化
  17. 景安服务器密码修改,[景安网络]提示页
  18. 个人电脑安全防范措施
  19. 快速应用计算机制作pop,【爆炸贴图片手绘字体】爆炸贴手绘技巧
  20. 【基于VS2010的MFC编程】多功能计算器转载与改进

热门文章

  1. 调用网易短信接口(发短信模板通知)
  2. 戴琼海院士:国际经济形势下滑,为何全球却在大力发展人工智能?
  3. 分享我每天的健康养生好习惯
  4. 腾讯云X惟客数据:云能力与行业产品方案融合,助力海外市场
  5. 炉石传说一直显示重新连接服务器,《炉石传说》:每次更新完之后一直卡在登录界面就是进不去...
  6. c++--定义图形抽象类。完成圆形、三角形、矩形的面积和周长计算
  7. CDR中是否有图层,如何调出图层面板?
  8. 华为麒麟芯片用在服务器上,细说华为麒麟芯片不对外出售的五大原因
  9. 辍学的了应该如何自我努力?
  10. 一志愿上岸哈尔滨工程大学计算机网安学硕811经验之初试