具体步骤分为数据采集脚本,数据收取服务,数据分析脚本,数据存储服务

采集脚本一般有两种形式,一种是简单的页面插入一个图片进行请求,一种是复杂的动态生成js标签,引入一段js(这时采集服务器会网往客户端写cookie),js采集浏览器数据与cookie,然后发送请求。

数据收取服务一般为web服务,可以是apache,nginx,或者swoole,这里主要看采集的压力,适当做负载均衡,可以爱脚本端做,也可以在服务端做,注意客户端ip的穿透。

脚本分析可以使用任何脚本,例如php,python。

数据存储分为两部,一个是采集数据的存储,一个是分析之后的数据的存储,一般来讲原始数据是需呀保留的,所以原始数据采集可以使用文本保存在单机,或者使用redis等可固话的存储容器保存。

  选用不同的形式对扩展以后的服务有一定的影响,暂且不谈,在pv/uv只有几百万的站点,或者几千万的站点web服务压力基本不大,每天的原始数据存储会有几百M。

  细节上可以使用不同的技术,例如加入memcached缓存,使用多进程多线程等

我使用的方案是使用nginx做采集web服务器,使用js脚本采集数据,采集的数据按五分钟分500个文件存储避免文本的冲突,然后php五分钟定期处理数据,统计结果记入redis保存。

js采集脚本如下:

(function () {var c = {id: '{$sid}',dm: [{$dm}],nv: {$nv},vdur: {$vdur},age: {$age},rec: {$rec},uid: {$uid},cf : {$cf}};var l = !0,m = null,n = !1;var p = function () {function a(a) {/["\\\x00-\x1f]/.test(a) && (a = a.replace(/["\\\x00-\x1f]/g, function (a) {var b = d[a];if (b) return b;b = a.charCodeAt();return '\\u00' + Math.floor(b / 16) .toString(16) + (b % 16) .toString(16)}));return '"' + a + '"'}function b(a) {return 10 > a ? '0' + a : a}var d = {'': '\\b','\t': '\\t','\n': '\\n','\f': '\\f','\r': '\\r','"': '\\"','\\': '\\\\'};return function (d) {switch (typeof d) {case 'undefined':return 'undefined';case 'number':return isFinite(d) ? String(d)  : 'null';case 'string':return a(d);case 'boolean':return String(d);default:if (d === m) return 'null';if (d instanceof Array) {var f = ['['],h = d.length,k,g,u;for (g = 0; g < h; g++) switch (u = d[g], typeof u) {case 'undefined':case 'function':case 'unknown':break;default:k && f.push(','),f.push(p(u)),k = 1}f.push(']');return f.join('')}if (d instanceof Date) return '"' + d.getFullYear() + '-' + b(d.getMonth() + 1) + '-' + b(d.getDate()) + 'T' + b(d.getHours()) + ':' + b(d.getMinutes()) + ':' + b(d.getSeconds()) + '"';k = ['{'];for (h in d) if (Object.prototype.hasOwnProperty.call(d, h)) switch (g = d[h], typeof g) {case 'undefined':case 'unknown':case 'function':break;default:f && k.push(','),f = 1,k.push(p(h) + ':' + p(g))}k.push('}');return k.join('')}}}();function q(a, b) {var d = a.match(RegExp('(^|&|\\?|#)(' + b + ')=([^&#]*)(&|$|#)', ''));return d ? d[3] : m}function v(a) {return (a = (a = a.match(/^(https?:\/\/)?([^\/\?#]*)/)) ? a[2].replace(/.*@/, '')  : m) ? a.replace(/:\d+$/, '')  : a};function w(a, b) {if (window.sessionStorage) try {window.sessionStorage.setItem(a, b)} catch (d) {}}function x(a) {return window.sessionStorage ? window.sessionStorage.getItem(a)  : m};function y(a, b, d) {var e;d.f && (e = new Date, e.setTime(e.getTime() + d.f));document.cookie = a + '=' + b + (d.domain ? '; domain=' + d.domain : '') + (d.path ? '; path=' + d.path : '') + (e ? '; expires=' + e.toGMTString()  : '') + (d.r ? '; secure' : '')};function z(a, b) {var d = new Image,e = 'mini_yp_log_' + Math.floor(2147483648 * Math.random()) .toString(36);window[e] = d;d.onload = d.onerror = d.onabort = function () {d.onload = d.onerror = d.onabort = m;d = window[e] = m;b && b(a)};d.src = a};var A;function D() {if (!A) try {A = document.createElement('input'),A.type = 'hidden',A.style.display = 'none',A.addBehavior('#default#userData'),document.getElementsByTagName('head') [0].appendChild(A)} catch (a) {return n}return l}function E(a, b, d) {var e = new Date;e.setTime(e.getTime() + d || 31536000000);try {window.localStorage ? (b = e.getTime() + '|' + b, window.localStorage.setItem(a, b))  : D() && (A.expires = e.toUTCString(), A.load(document.location.hostname), A.setAttribute(a, b), A.save(document.location.hostname))} catch (f) {}}function H(a) {if (window.localStorage) {if (a = window.localStorage.getItem(a)) {var b = a.indexOf('|'),d = a.substring(0, b) - 0;if (d && d > (new Date) .getTime()) return a.substring(b + 1)}} else if (D()) try {return A.load(document.location.hostname),A.getAttribute(a)} catch (e) {}return m};function I(a, b, d) {a.attachEvent ? a.attachEvent('on' + b, function (b) {d.call(a, b)})  : a.addEventListener && a.addEventListener(b, d, n)};   function N(a, b) {return '[object ' + b + ']' === {}.toString.call(a)};function Z(a, b) {a = '.' + a.replace(/:\d+/, '');b = '.' + b.replace(/:\d+/, '');var d = a.indexOf(b);return - 1 < d && d + b.length == a.length}function wa(a, b) {a = a.replace(/^https?:\/\//, '');return 0 == a.indexOf(b)}function Y(a) {for (var b = 0; b < c.dm.length; b++) if ( - 1 < c.dm[b].indexOf('/')) {if (wa(a, c.dm[b])) return l} else {var d = v(a);if (d && Z(d, c.dm[b])) return l}return n}function ra(a) {for (var b = [], d = 0, e = R.length; d < e; d++) {var f = R[d],h = a.a[f];'undefined' != typeof h && '' !== h && b.push(f + '=' + encodeURIComponent(h))}d = a.a.et;(0 === d || 90 === d) && a.a.rt && b.push('rt=' + encodeURIComponent(a.a.rt));return b.join('&')}function na() {var a = 'Yp_cv_' + c.id;try {if (y(a, '', {domain: la(),path: ma(),f: - 1}), window.sessionStorage && window.sessionStorage.removeItem(a), window.localStorage) window.localStorage.removeItem(a);else if (D()) try {A.load(document.location.hostname),A.removeAttribute(a),A.save(document.location.hostname)} catch (b) {}} catch (d) {}}function ma() {for (var a = 0, b = c.dm.length; a < b; a++) {var d = c.dm[a];if ( - 1 < d.indexOf('/') && wa(document.location.href, d)) return d.replace(/^[^\/]+(\/.*)/, '$1') + '/'}return '/'}function la() {for (var a = document.location.hostname, b = 0, d = c.dm.length; b < d; b++) if (Z(a, c.dm[b])) return c.dm[b].replace(/(:\d+)?[\/\?#].*/, '');return a}function pa() {var a = x('Yp_unsent_' + c.id);if (a) for (var a = a.split(','), b = 0, d = a.length; b < d; b++) z(Q + '//' + decodeURIComponent(a[b]) .replace(/^https?:\/\//, ''), function (a) {            X(a)})}function X(a) {var b = x('Yp_unsent_' + c.id) || '';b && ((b = b.replace(RegExp(encodeURIComponent(a.replace(/^https?:\/\//, '')) .replace(/([\*\(\)])/g, '\\$1') + '(%26u%3D[^,]*)?,?', 'g'), '') .replace(/,$/, '')) ? w('Yp_unsent_' + c.id, b)  : window.sessionStorage && window.sessionStorage.removeItem('Yp_unsent_' + c.id))
    }function qa(a, b) {var d = x('Yp_unsent_' + c.id) || '',e = a.a.u ? '' : '&u=' + encodeURIComponent(document.location.href),d = encodeURIComponent(b.replace(/^https?:\/\//, '') + e) + (d ? ',' + d : '');w('Yp_unsent_' + c.id, d)}(function () {function a() {if (!a.b) {a.b = l;for (var b = 0, d = e.length; b < d; b++) e[b]()}}function b() {try {document.documentElement.doScroll('left')} catch (d) {setTimeout(b, 1);return}a()}var d = n,e = [],f;document.addEventListener ? f = function () {document.removeEventListener('DOMContentLoaded', f, n);a()}: document.attachEvent && (f = function () {'complete' === document.readyState && (document.detachEvent('onreadystatechange', f), a())});(function () {if (!d) if (d = l, 'complete' === document.readyState) a.b = l;else if (document.addEventListener) document.addEventListener('DOMContentLoaded', f, n),window.addEventListener('load', a, n);else if (document.attachEvent) {document.attachEvent('onreadystatechange', f);window.attachEvent('onload', a);var e = n;try {e = window.frameElement == m} catch (k) {}document.documentElement.doScroll && e && b()}}) ();return function (b) {a.b ? b()  : e.push(b)}}) () .b = n;function ta() {this.d = this.j = (new Date) .getTime();this.i = 0;'object' == typeof document.onfocusin ? (I(document, 'focusin', $(this)), I(document, 'focusout', $(this)))  : (I(window, 'focus', $(this)), I(window, 'blur', $(this)))}function $(a) {return function (b) {if (!(b.target && b.target != window)) {if ('blur' == b.type || 'focusout' == b.type) a.i += (new Date) .getTime() - a.d;a.d = (new Date) .getTime()}}}function sa(a) {return function () {a.a.nv = 0;a.a.st = 4;a.a.et = 3;a.a.ep = (new Date) .getTime() - a.e.j + ',' + ((new Date) .getTime() - a.e.d + a.e.i);W(a)}}    function W(a) {a.a.rnd = Math.round(2147483647 * Math.random());a.a.api = a.a.api || a.c ? a.a.api + '_' + a.c : '';var b = Q + '//{$callurl}?' + ra(a);a.a.api = 0;a.c = 0;qa(a, b);z(b, function (a) {X(a)})}var aa = navigator.cookieEnabled,ba = navigator.javaEnabled(),ha = navigator.language || navigator.browserLanguage || navigator.systemLanguage || navigator.userLanguage || '',ia = (window.screen.width || 0) + 'x' + (window.screen.height || 0),ja = window.screen.colorDepth || 0;var O = 0,P = Math.round( + new Date / 1000),Q = 'https:' == document.location.protocol ? 'https:' : 'http:',//参数数组//cc : 是否支持写数据到浏览器(cookie,sessionStorage,localStorage,userData)//ck : 是否支持cookie//cl : 浏览器颜色位数//ds : 浏览器分辨率//ep : 事件描述//et : 事件类型,默认是0为一般统计,3为关闭事件//fl : flash版本//ja : 是否支持java//ln : 浏览器语言//lt : 30天内的最后一次首次访问的时间,首次访问为空//nv : 是否开启一次新访问,可以理解为uv,但是不是独立访客//rnd: 随机数//si : 统计id,站点标示//st : 外域来源为3,本域为1,4//su : 来源url//v  : 当前脚本版本//cv : 用户自定义数据//lv : 当月新访问<4 为2 ,=4 为3, =0 为1,可以理解为客户新访问频次//api: 未知,与事件相关//tt : 站点title//u  : 站点url//cf : m点 1,站点0//uid : 会员id//pt : 平台//ocu : 操作系统//ua : 浏览器类型
    R = 'cc ck cl ds ep et fl ja ln lt nv rnd si st su v cv lv api tt u gt cf uid pt ocu ua'.split(' ');function V() {if ('undefined' == typeof window['_yphm_loaded_' + c.id]) {window['_yphm_loaded_' + c.id] = l;var a = this;a.a = {};a.q = [];a.p = {push: function () {a.k.apply(a, arguments)}};a.c = 0;a.h = n;ka(a)}}V.prototype = {getData: function (a) {try {var b = RegExp('(^| )' + a + '=([^;]*)(;|$)') .exec(document.cookie);return (b ? b[2] : m) || x(a) || H(a)} catch (d) {}},setData: function (a, b, d) {try {y(a, b, {domain: la(),path: ma(),f: d}),d ? E(a, b, d)  : w(a, b)} catch (e) {}},k: function (a) {if (N(a, 'Array')) {var b = function (a) {return a.replace ? a.replace(/'/g, '\'0') .replace(/\*/g, '\'1') .replace(/!/g, '\'2')  : a},d = function (a) {for (var b in a) if ({}.hasOwnProperty.call(a, b)) {var e = a[b];N(e, 'Object') || N(e, 'Array') ? d(e)  : a[b] = String(e)}};switch (a[0]) {case '_trackPageview':if (1 <a.length && a[1].charAt && '/' == a[1].charAt(0)) {this.a.api |= 4;this.a.et = 0;this.a.ep = '';this.h ? (this.a.nv = 0, this.a.st = 4)  : this.h = l;var b = this.a.u,e = this.a.su;this.a.u = Q + '//' + document.location.host + a[1];this.a.su = document.location.href;W(this);this.a.u = b;this.a.su = e}break;case '_trackEvent':2 < a.length && (this.a.api |= 8, this.a.nv = 0, this.a.st = 4, this.a.et = 4, this.a.ep = b(a[1]) + '*' + b(a[2]) + (a[3] ? '*' + b(a[3])  : '') + (a[4] ? '*' + b(a[4])  : ''), W(this));break;case '_setCustomVar':if (4 > a.length) break;var e = a[1],f = a[4] || 3;if (0 <e && 6 > e && 0 < f && 4 > f) {this.c++;for (var h = (this.a.cv || '*') .split('!'), k = h.length; k < e - 1; k++) h.push('*');h[e - 1] = f + '*' + b(a[2]) + '*' + b(a[3]);this.a.cv = h.join('!');a = this.a.cv.replace(/[^1](\*[^!]*){2}/g, '*') .replace(/((^|!)\*)+$/g, '');'' !== a ? this.setData('Yp_cv_' + c.id, encodeURIComponent(a), c.age)  : na()}break;case '_trackOrder':a = a[1];N(a, 'Object') && (d(a), this.a.api |= 16, this.a.nv = 0, this.a.st = 4, this.a.et = 94, this.a.ep = p(a), W(this));break;case '_trackMobConv':if (a = {webim: 1,tel: 2,map: 3,sms: 4,callback: 5,share: 6}[a[1]]) this.a.api |=32,this.a.et = 93,this.a.ep = a,W(this);break;case '_trackRTPageview':a = a[1];N(a, 'Object') && (d(a), a = p(a), 512 >= encodeURIComponent(a) .length && (this.a.api |= 64, this.a.rt = a));break;case '_trackRTEvent':a = a[1],N(a, 'Object') && (d(a), a = p(a), 1024 >= encodeURIComponent(a) .length && (b = this.a.rt, this.a.api |= 128, this.a.et = 90, this.a.rt = a, W(this), this.a.rt = b))}}}};function ka(a) {try {var b,d,e,f,h,k,g;O = a.getData('Yp_lpvt_' + c.id) || 0;13 == O.length && (O = Math.round(O / 1000));if (document.referrer) {var u = n;if (Y(document.referrer) && Y(document.location.href)) u = l;else var oa = v(document.referrer),u = Z(oa || '', document.location.hostname);d = u ? P - O > c.vdur ? 1 : 4 : 3} else d = P - O > c.vdur ? 1 : 4;b = 4 != d ? 1 : 0;if (k = a.getData('Yp_lvt_' + c.id)) {g = k.split(',');for (var F = g.length - 1; 0 <= F; F--) 13 == g[F].length && (g[F] = '' + Math.round(g[F] / 1000));for (; 2592000 < P - g[0]; ) g.shift();h = 4 > g.length ? 2 : 3;for (1 === b && g.push(P); 4 <g.length; ) g.shift();k = g.join(',');f = g[g.length - 1]} else k = P,f = '',h = 1;a.setData('Yp_lvt_' + c.id, k, c.age);a.setData('Yp_lpvt_' + c.id, P);e = P == a.getData('Yp_lpvt_' + c.id) ? '1' : '0';if (0 == c.nv && Y(document.location.href) && ('' == document.referrer || Y(document.referrer))) b = 0,d = 4;a.a.nv = b;a.a.st = d;a.a.cc = e;a.a.lt = f;a.a.lv = h;a.a.si = c.id;a.a.uid = c.uid;a.a.cf = c.cf;a.a.su = document.referrer;a.a.u  = document.location.href;a.a.pt = navigator.platform;var ua = navigator.userAgent.toLowerCase();var s;if(s = ua.match(/msie ([\d.]+)/)) a.a.ua = 'IE' + s[1];else if(s = ua.match(/firefox\/([\d.]+)/)) a.a.ua = 'Firefox' + s[1];else if(s = ua.match(/chrome\/([\d.]+)/))a.a.ua = 'Chrome' + s[1];else if(s = ua.match(/opera.([\d.]+)/))  a.a.ua = 'Opera' + s[1];else if(s = ua.match(/version\/([\d.]+).*safari/))   a.a.ua = 'Safari' + s[1];else a.a.ua = 'unknown';a.a.ocu = navigator.oscpu;a.a.ds = ia;a.a.cl = ja + '-bit';a.a.ln = ha;a.a.ja = ba ? 1 : 0;a.a.ck = aa ? 1 : 0;var J = a.a;b = '';if (navigator.plugins && navigator.mimeTypes.length) {var B =navigator.plugins['Shockwave Flash'];B && B.description && (b = B.description.replace(/^.*\s+(\S+)\s+\S+$/, '$1'))} else if (window.ActiveXObject) try {var ca = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');ca && (b = ca.GetVariable('$version')) && (b = b.replace(/^.*\s+(\d+),(\d+).*$/, '$1.$2'))} catch (ya) {}J.fl = b;a.a.v = '1.0.0';a.a.cv = decodeURIComponent(a.getData('Yp_cv_' + c.id) || '');(a.a.tt = document.title || '')//屏蔽不是新uv不记录tt//1 == a.a.nv && (a.a.tt = document.title || '');//暂时不清楚,18touch里没有看到这个参数a.a.api = 0;//var G = document.location.href;//a.a.cm = q(G, 'hmmd') || '';0 == a.a.nv ? pa()  : X('.*');if (c.rec) a.a.nv ? (a.g = encodeURIComponent(document.referrer), window.sessionStorage ? w('Yp_from_' + c.id, a.g)  : E('Yp_from_' + c.id, a.g, 86400000))  : a.g = (window.sessionStorage ? x('Yp_from_' + c.id)  :H('Yp_from_' + c.id)) || '';a.e = new ta;//I(window, 'beforeunload', sa(a));var t = window._hmt;if (t && t.length) for (r = 0; r < t.length; r++) {var C = t[r];switch (C[0]) {case '_setAccount':1 < C.length && /^[0-9a-z]{32}$/.test(C[1]) && (a.a.api |= 1, window._yphm_account = C[1]);break;case '_setAutoPageview':if (1 < C.length) {var U = C[1];if (n === U || l === U) a.a.api |= 2,window._yphm_autoPageview = U}}}if ('undefined' === typeof window._yphm_account || window._yphm_account === c.id) {window._yphm_account = c.id;var M = window._hmt;if (M &&M.length) for (var t = 0, xa = M.length; t < xa; t++) a.k(M[t]);window._hmt = a.p}if ('undefined' === typeof window._yphm_autoPageview || window._yphm_autoPageview === l) a.h = l,a.a.et = 0,a.a.ep = '',W(a)} catch (ga) {a = [],a.push('si=' + c.id),a.push('n=' + encodeURIComponent(ga.name)),a.push('m=' + encodeURIComponent(ga.message)),a.push('r=' + encodeURIComponent(document.referrer)),z(Q + '//{$callurl}?' + a.join('&'))}}new V;
}) ();

脚本的函数说明如下:

//定义p方法,将传入的参数转换为字符串形式

//定义q方法,从字符串a里找出含有字符串b的值,如果没有则为null,貌似是从url请求参数里获取值

//定义v方法,取url中协议后的第一个/之前的内容并将端口号去掉,例如http://www.18touch.com:999/ 过滤之后得到www.18touch.com

//定义w方法,在html5的属性sessionStorage里存放window.sessionStorage[a]=b;,百度统计存放的是访问时间,估计用于计算回话时间

//定义x方法,在html5的属性sessionStorage里取出w方法定义的key为a的值,不支持这个属性返回null

//定义y方法,设置cookie,a=b,cookie的属性在d对象里面

//定义z方法,请求a地址,并做记录,在请求完成,出错,拒绝之后,重置。如果定义了回调b方法,则执行b(a);

//定义D方法,全局变量A为空则执行将A变成一个userdata对象,用于ie浏览器储存数据,报错返回false;全局变量A不为空返回true;

//定义E方法,如果支持window.localStorage,则保持window.localStorage[a]=now+d|b,如果不支持再看是否支持userdata,如果支持,在域名下使用userdata存储a=b,过期时间为now+d

//定义H方法,如果没有过期的话取出从E方法存储的key为a的值,否则返回null。

//定义I方法,在a元素上绑定事件b,处理函数为d

//定义N方法,判读a的类型是否为b

//定义V方法,启动统计功能

//定义V原型方法,

//定义pa方法,从sessionStorage里取Hm_unsent_字符串,按,分隔,依次调用z方法发送请求,并调用回调函数X

//定义X方法,用作请求后的回调,去掉sessionStorage里的Hm_unsent_字符串里的请求url,如果Hm_unsent_为空,删除Hm_unsent_

//定义qa方法,在sessionStorage里的key:Hm_unsent_后添加url b,如果a.a.u存在,后面还要添加&u=当前url的后缀

//定义W方法,调用qa往sessionStorage的Hm_unsent_里存储url:hm.baidu.com/hm.gif,调用z方法发送请求,并执行回调X

//定义sa方法,返回一个初始化a.a数组,并执行触发请求的方法,在window.beforeunload触发,关闭页面时触发

//定义ka方法,执行信息收集与消息发送,以及事件监听

//定义ra方法,组装R请求的字符串,数据从a.a数组里面获取

//定义na方法,从cookie,sessionStorage,localStorage,usedata删除Hm_cv_

//定义ma方法,如果当前href在以域名配置数组里的开头,返回/以及之后的部分

//定义la方法,取当前域名,如果域名数组里有当前域名结尾的,返回域名数组里的配置项,否则返回当前域名

//定义Y方法,判断url a的域是否在域数组里

//定义wa方法,判断字符串b是否是url a的开头

//定义Z方法,判断去除端口号之后的url b,是否是 url a的结尾部分

//定义ta方法,绑定window的focusin,focusout事件,需要浏览器支持a.j为加载后的时间

//定义$方法,检测window的focus与blur事件,计算a.d为最后操作时间,a.i为操作累计时间

WEB服务段的输出这段脚本的php为:

error_reporting(0);date_default_timezone_set("PRC");$environment = get_cfg_var('app_flow_develop') ? get_cfg_var('app_flow_develop') : 3;define('BASEPATH',dirname(dirname(__FILE__)));switch($environment){    case 1 :        require BASEPATH . DIRECTORY_SEPARATOR . 'conf' . DIRECTORY_SEPARATOR . 'config.product.php';        break;    case 2 :        require BASEPATH . DIRECTORY_SEPARATOR . 'conf' . DIRECTORY_SEPARATOR . 'config.product.php';        break;    default:        require BASEPATH . DIRECTORY_SEPARATOR . 'conf' . DIRECTORY_SEPARATOR . 'config.develop.php';        break;}$sid = addslashes($_GET['sid']);$uid = isset($_GET['uid'])? addslashes($_GET['uid']) : null;$cf  = isset($_GET['cf'])? addslashes($_GET['cf']) : null;if(array_key_exists($sid,$config)){

    //检查账户,没有就写一个    if(!isset($_COOKIE['YPTJACCOUNT'])){        setcookie('YPTJACCOUNT',$sid,time () + 3600 * 24 * 365 * 5 ,  "/" ,  $tjdomain);    }

    //检查UV标识,没有就种一个    if(!isset($_COOKIE['YPTJUUID'])){        $now = time ();        $pretime = strtotime('tomorrow') - $now;        setcookie('YPTJUUID',uniqid(true),$now + $pretime ,  "/" ,  $tjdomain);    }

    //有会员则覆盖js配置    if($uid){        $config[$sid]['uid'] = $uid;    }

    //判断网站还是m站    if($cf){        switch($cf){            case 1   : $config[$sid]['cf'] = 1;break;            default  : $config[$sid]['cf'] = 0;break;        }    }

    //判断js缓存    $lastmodifytime = filemtime(BASEPATH . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR .'yptj.js');    if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {      $browserCachedCopyTimestamp = strtotime(preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']));      //if($browserCachedCopyTimestamp >= $lastmodifytime){      if($browserCachedCopyTimestamp + $interval > time()){        header("http/1.1 304 Not Modified");        exit;      }    }

    //header ("Last-Modified: " . gmdate ('r', $lastmodifytime));    //header ("Expires: " . gmdate ("r", ($lastmodifytime + $interval)));    header ("Last-Modified: " . gmdate ('r', time()));    header ("Expires: " . gmdate ("r", (time() + $interval)));    header ("Cache-Control: max-age={$interval}");    $js = file_get_contents(BASEPATH . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR .'yptj.js');    $js = str_replace($replace_a,$config[$sid],$js);    echo $js;    exit;}else{    exit;}

web页面插入的动态脚本为:

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>超好玩</title></head><body>hello,index<script type="text/javascript">//0c998ee80e953443caf0cf6b5ba7b5dbvar _yphmProtocol = (("https:" == document.location.protocol) ? "https://" : "http://");document.write(unescape('%3Cscript src="' + _yphmProtocol + 'hm.tj.com/h.js%3F0c998ee80e953443caf0cf6b5ba7b5db" type="text/javascript"%3E%3C/script%3E'));  </script></body>
</html>

配置文件为

//接收地址
$tjdomain = 'hm.tj.com';
//统计账号配置信息
$config = array('0c998ee80e953443caf0cf6b5ba7b5db'=>array('0c998ee80e953443caf0cf6b5ba7b5db',"{$tjdomain}/hm.php","'18touch.com'",-1,1800000,31536000000,0,0,0),
);
//js文件过期时间
$interval = 60 * 60 * 24 * 7; // 1 week
//置换数组
$replace_a = array('{$sid}','{$callurl}','{$dm}','{$nv}','{$vdur}','{$age}','{$rec}','{$uid}','{$cf}'
);
//日志数据的记录目录
$LOG_BASE = BASEPATH . DIRECTORY_SEPARATOR . "data";
//redis数据库配置
$REDIS_IP = '127.0.0.1';
$REDIS_PORT = 6379;

转载于:https://www.cnblogs.com/kudosharry/p/3904726.html

PHP实现站点pv,uv统计(一)相关推荐

  1. spark sql uv_使用Spark Streaming SQL进行PV/UV统计

    作者:关文选,花名云魄,阿里云E-MapReduce 高级开发工程师,专注于流式计算,Spark Contributor 1.背景介绍 PV/UV统计是流式分析一个常见的场景.通过PV可以对访问的网站 ...

  2. spark sql uv_使用Spark Streaming SQL进行PV/UV统计-阿里云开发者社区

    作者:关文选,花名云魄,阿里云E-MapReduce 高级开发工程师,专注于流式计算,Spark Contributor 1.背景介绍 PV/UV统计是流式分析一个常见的场景.通过PV可以对访问的网站 ...

  3. 浅析网站PV/UV统计系统的原理及其设计

    国庆节前有段时间,新浪的"图床"一直不大稳定,因为新浪开启了防盗链,果然免费的永远是最贵的啊.为了不影响使用,我非常粗暴地禁止了浏览器发送Referer,然后我就发现了一件尴尬的事 ...

  4. 实现pv uv统计_程序员修仙之路优雅快速的统计千万级别uv

    菜菜,咱们网站现在有多少PV和UV了? Y总,咱们没有统计pv和uv的系统,预估大约有一千万uv吧 写一个统计uv和pv的系统吧 网上有现成的,直接接入一个不行吗? 别人的不太放心,毕竟自己写的,自己 ...

  5. [svc][op]从历险压缩日志里网站pv uv统计

    http://myhoop.blog.51cto.com/5556534/1367523 tomcat日志格式: http://www.cnblogs.com/anic/archive/2012/12 ...

  6. 实现pv uv统计_聊聊前端监控(二)--行为监控的技术实现

    上一篇梳理了前端监控的主要场景和类型,从本文开始,讨论下我知道的一些技术实现.前端黑科技层出不穷,个人眼界有限,尽量把了解到的实现方式都罗列出来,希望对大家有些启发,同时也欢迎流言讨论. 限于篇幅,按 ...

  7. java pv uv 统计_shell统计pv和uv、独立ip的方法

    每天分析日志的哥们实在伤不起,经常需要给出PV,UV,独立IP等一些统计值,使用C/C++,java都可以写,过程是这样的,先读取文件,逐行扫描,把能标记的值放入数据结构中,排重得出最终结果,其实Li ...

  8. php+pv统计代码实现,Laravel 10 行代码实现简单的网站 pv uv 统计

    最近在优化博客呀,想做一个统计网站 pv uv 的功能,虽然有第三的统计平台再用,但还是想自己写一个啊. 其实统计的数据非常简单,就是网站的访问量丶访客量. public function __con ...

  9. 有关“数据统计”的一些概念 -- PV UV VV IP跳出率等

    有关"数据统计"的一些概念 -- PV UV VV IP跳出率等 1. 什么是展现量.点击量.点击率 在百度推广后台可以看到消费.平均价格.点击.展现.点击率.千次展现费用等数据, ...

  10. java统计 pv uv_统计网址的pv,uv(附带Spring定时器)

    之前做了一个统计商铺的PV,UV值 大体思路:每天将用户的访问信息放到明细表里,然后在第二天的凌晨将这些数据归总 PVUV表 4个字段:主键pk    用户IP(customer_ip)    访问时 ...

最新文章

  1. 两边放动物对战守城的游戏_集合啦!动物森友会定制周边;百战天虫 大混战发布...
  2. Hadoop入门连接
  3. DataGridView中的rows.Count比实际行数多1的原因以及解决办法
  4. 使用SaxParser和完整代码进行XML解析
  5. html的排版标题的是,HTML 5结构排版布局
  6. 用Vue.js开发微信小程序:开源框架mpvue解析
  7. Spark GraphX算法 - Connected Components(连通分支)算法
  8. ARDUINO使用GPRS发送GPS数据到OneNet测试
  9. LeetCode 590. N叉树的后序遍历(N-ary Tree Postorder Traversal)
  10. 两个tplink路由器有线桥接_如何装2个tplink无线路由器_两个tplink路由器怎么设置?-192路由网...
  11. 解决WinHTTP Web Proxy Auto-Discovery Service无法启动问题
  12. dingo php,Laravel+Dingo/Api 自定义响应 | 码农网
  13. python怎么选取不连续的列_用pandas中的DataFrame时选取行或列的方法
  14. VM中的Ubuntu能ping通外网浏览器不能上网
  15. 手把手教你做一个天气时钟,推荐收藏
  16. 为什么以及如何通过机器人学习编程和项目实践
  17. 模拟丢包、慢网速的测试工具
  18. seo刷流量软件有哪些|比较好的有什么呢|seo排名软件
  19. BFC、IFC、GFC 和 FFC的概念
  20. 我用wxPython搭建GUI量化系统之财务选股工具剔除ST股和次新股

热门文章

  1. Android Q Data Setup For Long Connection
  2. 以太网协议 | ARP协议详解-ARP报文结构解析
  3. 常用测速网站及工具(IPv4/IPv6)
  4. Microsoft Office 2007 注册码office Visio 2007 注册码
  5. 手机Root与刷机教程
  6. 和讯博客知名博主《猎杀黑马》作者王宁签售会圆满结束
  7. 【业务安全02】业务数据安全
  8. linux能力集机制,Linux能力(capability)机制的继承
  9. 我的个人网站,终于上线了!
  10. 现金流量表的编制 (by shany shang)