Laravel 页面 PV 统计实例,laravelpv


目录

统计进行的背景

统计的构思

统计的代码实现


 

  • 需求背景

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

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

  • 统计的构思

    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); // 第三个参数表明是同步的 xhr
        client.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记录用户在网站的浏览记录和停留时间

 

 

相关内容

    暂无相关文章