数据分析脚本如下:
//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; } //删除其他的配置项 unset($tjdomain);unset($config);unset($interval);unset($replace_a); require BASEPATH . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'logger.class.php'; //0//cc : 是否支持写数据到浏览器(cookie,sessionStorage,localStorage,userData) //1//ck : 是否支持cookie //2//cl : 浏览器颜色位数 //3//ds : 浏览器分辨率 //4//fl : flash版本 //5//ja : 是否支持java //6//ln : 浏览器语言 //7//si : 统计id,站点标示 //8//su : 来源url,只取了域名 //9//kd : 关键词 //10//tt : 站点title //11//cf : m点 1,站点0 //12//uid : 会员id //13//pt : 平台 //14//ocu : 操作系统 //15//ua : 浏览器类型 //16//tm : 请求时间 //17//ip : 请求ip //18//u : 站点url //19//uuid:唯一用户标识 //20//basesu:原始su //21//baseu:原始u //22//basekd:原始关键词 //23//u1:一级连接 //24//u2:二级连接 //25//u3:三级连接 //26//u4:四级连接
//获得时间节点 $time = time(); $Ymd = date("Ymd",$time); $H = date("G",$time); $i = floor(date("i",$time)/5);
//处理昨天的最后一个五分钟区间 if(0 == $i && 0 == $H){ $Ymd = date("Ymd",strtotime('-1 days')); $H = 23; $i = 11; } //处理今天上一个小时的最后一个五分钟区间 elseif(0 == $i && 0 != $H){ $H--; $i = 11; } //处理上一个五分钟区间 else{ $i--; }
//手动控制脚本的执行目录 if(isset($_SERVER['argv'][1]) && $_SERVER['argv'][1]){ if(isset($_SERVER['argv'][2]) && isset($_SERVER['argv'][3]) && $_SERVER['argv'][2] >=0 && $_SERVER['argv'][2] < 24 && $_SERVER['argv'][3] >=0 && $_SERVER['argv'][3] <12) { $Ymd = strval($_SERVER['argv'][1]); $H = strval($_SERVER['argv'][2]); $i = strval($_SERVER['argv'][3]); $handd0 = true; }else{ echo 'parma error'; } }
//设置redis的key与操作目录地址 $LOG_PATH = $LOG_BASE . DIRECTORY_SEPARATOR . $Ymd . DIRECTORY_SEPARATOR . $H . DIRECTORY_SEPARATOR . $i; $HOUR_PATH = dirname($LOG_PATH); $REDIS_DAY_KEY = $Ymd; $REDIS_HOUR_KEY = "{$Ymd}:{$H}";
$log_base = new Logger($LOG_BASE . DIRECTORY_SEPARATOR . 'error.log');
//小时路径下的记录句柄,先检查有没有小时目录,没有的话报错 if(file_exists($HOUR_PATH)){ $log_hour = new Logger($HOUR_PATH . DIRECTORY_SEPARATOR . 'error.log'); }else{ if(isset($handd0) && true === $handd0){ echo $HOUR_PATH . ' is not exists please check the dir and retry'; $log_base -> error($HOUR_PATH . ' is not exists by hand'); }else{ $log_base -> error($HOUR_PATH . ' is not exists '); } exit; } //如果有日志 //这里的代码可以封装成一个类,当做一种对最小单元的一个处理方法,或者可以换成其他语言的脚本的调用,也方便单独手动处理数据 //优化可以使用popen,proc_open,pcntl等方法多进程来处理 if(file_exists($LOG_PATH)){ //分钟路径下的记录句柄 $log_do = new Logger($LOG_PATH . DIRECTORY_SEPARATOR . 'do.txt'); //切换目录,不然window下报错 chdir($LOG_PATH); //判断是否完成这个区间 if(!file_exists($LOG_PATH . '/done.txt')){ //生成合并文件 if(!file_exists($LOG_PATH . '/all.log')){ $log_do -> notice(" combine files starts "); if(PHP_OS == 'WINNT'){ system("copy *.log all.log"); } else { system("cat *.log >> all.log"); } //再次判断 if(!file_exists($LOG_PATH . '/all.log')){ $log_hour -> error(" No.{$i} all log combine error"); exit; } $log_do -> notice(" combine files ends "); } //读取文件写redis缓存 $log_do -> notice(" read all_log starts "); if($fp = fopen ($LOG_PATH . '/all.log', "r")){ if(flock($fp , LOCK_SH )) { //初始化 $redis = new Redis(); $re = $redis->pconnect($REDIS_IP,$REDIS_PORT); if(!$re){ $REDIS_FLAG = FALSE; }else{ $REDIS_FLAG = TRUE; //全站新的ip,uv,uid $uv_new = $uid_new = $ip_new = array(); //u的新uv,su的新uv,kw的新uv $u_uv = $su_uv = $kw_uv = array();
} $ii=1; //记录这段时间的pv $si_array = $uv_array = $uid_array = $ip_array = $u_array = $su_array = $kw_array = array(); //读取文件,填充数组 while($str = fgets($fp)){ //移除回车符 $str = trim($str,PHP_EOL); $a = explode('~^~',$str); if(27 != count($a)){ $log_do -> notice(" No.{$ii} data is bad type "); continue; } //填充数组 if($a[7]){ //处理si,根据si再次初始化数组 //记录每个站点这段时间的pv总数 /* $si_array( '站点一'=>10, '站点二'=>'20' ); */ if(isset($si_array[$a[7]])) { $si_array[$a[7]] += 1; } else { $si_array[$a[7]] = 1; $uv_new[$a[7]] = $uid_new[$a[7]] = $ip_new[$a[7]] = array(); $u_uv[$a[7]] = $su_uv[$a[7]] = $kw_uv[$a[7]] = array(); $uv_array[$a[7]] = $uid_array[$a[7]] = $ip_array[$a[7]] = $kw_array[$a[7]] = $su_array[$a[7]] = $u_array[$a[7]] = array(); $si_array[$a[7]] = 1; }
//处理uv if($a[19]){ //记录uv,记录后得到每个站点,每个uuid这段时间的pv数量 /* $uv_array = array( '站点一'=>array( 'uuid1'=>10, 'uuid2'=>20, ) ) */ isset($uv_array[$a[7]][$a[19]]) ? $uv_array[$a[7]][$a[19]] += 1 : $uv_array[$a[7]][$a[19]] = 1; //记录每个站点,这段时间的新的uv数量 /* $uv_new = array( '站点一'=>array( 'uuid1','uuid2' ) ) */ if($REDIS_FLAG){ //不在这个时间段记录的数据里 if(!in_array($a[19],$uv_new[$a[7]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:UV:HASH",$a[19]); //不在今天的历史数据里(即新的uuid) if(!$exist){ $uv_new[$a[7]][]= $a[19]; } } } } //处理uid if($a[12]){ //记录uid,记录后得到每个站点,每个uid这段时间的pv数量 /* $uid_array = array( '站点一'=>array( 'uid1'=>10, 'uid2'=>20, ) ) */ isset($uid_array[$a[7]][$a[12]]) ? $uid_array[$a[7]][$a[12]] += 1 : $uid_array[$a[7]][$a[12]] = 1; //记录每个站点,这段时间的新的uid数量 /* $uid_new = array( '站点一'=>array( 'uid1','uid2' ) ) */ if($REDIS_FLAG){ if(!in_array($a[12],$uid_new[$a[7]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:UID:HASH",$a[12]); if(!$exist){ $uid_new[$a[7]][]= $a[12]; } } } } //处理ip if($a[17]){ //记录ip,记录后得到每个站点,每个ip这段时间的pv数量 /* $ip_array = array( '站点一'=>array( 'ip1'=>10, 'ip2'=>20, ) ) */ isset($ip_array[$a[7]][$a[17]]) ? $ip_array[$a[7]][$a[17]] += 1 : $ip_array[$a[7]][$a[17]] = 1; //记录每个站点,这段时间的新的ip数量 /* $ip_new = array( '站点一'=>array( 'ip1','ip2' ) ) */ if($REDIS_FLAG){ if(!in_array($a[17],$ip_new[$a[7]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:IP:HASH",$a[17]); if(!$exist){ $ip_new[$a[7]][]= $a[17]; } } } } //特殊处理的项 //处理u if($a[18]){ //处理一级Url reg_u_common_op(23); //处理二级Url reg_u_common_op(24); //处理三级Url reg_u_common_op(25); //处理四级Url reg_u_common_op(26); } //处理kw if($a[9]){ //记录kw,记录后得到每个站点,每个kw这段时间的pv数量 /* $kw_array = array( '站点一'=>array( 'kw1'=>10, 'kw2'=>20, ) ) */ isset($kw_array[$a[7]][$a[9]]) ? $kw_array[$a[7]][$a[9]] += 1 : $kw_array[$a[7]][$a[9]] = 1; //记录每个站点,这段时间kw的新的uv数量 /* $kw_new = array( '站点一'=>array( 'kw1'=>array( 'uuid1','uuid2' ) ) ) */ if($REDIS_FLAG){ if(!isset($kw_uv[$a[7]][$a[9]]) || !in_array($a[19],$kw_uv[$a[7]][$a[9]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:{$a[9]}:KW:UV:HASH",$a[19]); if(!$exist){ $kw_uv[$a[7]][$a[9]][]= $a[19]; } } } } //处理su if($a[8]){ //记录su,记录后得到每个站点,每个su这段时间的pv数量 /* $su_array = array( '站点一'=>array( 'su1'=>10, 'su2'=>20, ) ) */ isset($su_array[$a[7]][$a[8]]) ? $su_array[$a[7]][$a[8]] += 1 : $su_array[$a[7]][$a[8]] = 1; //记录每个站点,这段时间su的新的uv数量 /* $kw_new = array( '站点一'=>array( 'kw1'=>array( 'uuid1','uuid2' ) ) ) */ if($REDIS_FLAG){ if(!isset($su_uv[$a[7]][$a[8]]) || !in_array($a[19],$su_uv[$a[7]][$a[8]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:{$a[8]}:SU:UV:HASH",$a[19]); if(!$exist){ $su_uv[$a[7]][$a[8]][]= $a[19]; } } } }
}else{ $log_do -> notice(" No.{$ii} data empty si "); continue; }
$ii++; unset($a); } $log_do -> notice(" read all_log is complete "); //填充redis //记录redis记录开始 if($REDIS_FLAG){ $log_do -> notice(" set redis start "); //记录站点的pv总数 foreach($si_array as $k => $v){ $redis->HINCRBY("{$REDIS_DAY_KEY}:{$k}:QZ:HASH","PV",$v); $redis->HINCRBY("{$REDIS_HOUR_KEY}:{$k}:QZ:HASH","PV",$v); } //记录站点的uv总数 foreach($uv_new as $k => $v){ $uv_num = count($v); $redis->HINCRBY("{$REDIS_DAY_KEY}:{$k}:QZ:HASH","UV",$uv_num); $redis->HINCRBY("{$REDIS_HOUR_KEY}:{$k}:QZ:HASH","UV",$uv_num); //插入当天的uv唯一hash $flip_uv = array_flip($v); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:UV:HASH",$flip_uv); } //记录站点的uid总数 foreach($uid_new as $k => $v){ $uid_num = count($v); $redis->HINCRBY("{$REDIS_DAY_KEY}:{$k}:QZ:HASH","UID",$uid_num); $redis->HINCRBY("{$REDIS_HOUR_KEY}:{$k}:QZ:HASH","UID",$uid_num); //插入当天的uv唯一hash $flip_uid = array_flip($v); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:UID:HASH",$flip_uid); } //记录站点的ip总数 foreach($ip_new as $k => $v){ $ip_num = count($v); $redis->HINCRBY("{$REDIS_DAY_KEY}:{$k}:QZ:HASH","IP",$ip_num); $redis->HINCRBY("{$REDIS_HOUR_KEY}:{$k}:QZ:HASH","IP",$ip_num); //插入当天的uv唯一hash $flip_ip = array_flip($v); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:IP:HASH",$flip_ip); } //记录站点u的pv,uv foreach($u_uv as $k => $v){ foreach($v as $kk => $vv){ $u_uv_num = count($vv); $u_pv_num = $u_array[$k][$kk]; $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:U:PV:ZSET",$u_pv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:U:PV:ZSET",$u_pv_num,$kk); $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:U:UV:ZSET",$u_uv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:U:UV:ZSET",$u_uv_num,$kk); //插入当天的uv唯一hash $flip_u_uv = array_flip($vv); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:{$kk}:U:UV:HASH",$flip_u_uv); } } //记录站点kw的pv,uv foreach($kw_uv as $k => $v){ foreach($v as $kk => $vv){ $kw_uv_num = count($vv); $kw_pv_num = $kw_array[$k][$kk]; $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:KW:PV:ZSET",$kw_pv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:KW:PV:ZSET",$kw_pv_num,$kk); $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:KW:UV:ZSET",$kw_uv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:KW:UV:ZSET",$kw_uv_num,$kk); //插入当天的uv唯一hash $flip_kw_uv = array_flip($vv); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:{$kk}:KW:UV:HASH",$flip_kw_uv); } } //记录站点su的pv,uv foreach($su_uv as $k => $v){ foreach($v as $kk => $vv){ $su_uv_num = count($vv); $su_pv_num = $su_array[$k][$kk]; $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:SU:PV:ZSET",$su_pv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:SU:PV:ZSET",$su_pv_num,$kk); $redis->ZINCRBY("{$REDIS_DAY_KEY}:{$k}:SU:UV:ZSET",$su_uv_num,$kk); $redis->ZINCRBY("{$REDIS_HOUR_KEY}:{$k}:SU:UV:ZSET",$su_uv_num,$kk); //插入当天的uv唯一hash $flip_su_uv = array_flip($vv); $redis->HMSET("{$REDIS_DAY_KEY}:{$k}:{$kk}:SU:UV:HASH",$flip_su_uv); } } $log_do -> notice(" set redis is complete "); } //记录redis记录结束 //记录统计数据 //记录统计记录开始 $log_do -> notice(" write analyse data starts "); if($REDIS_FLAG){ file_put_contents($LOG_PATH . '/uv_new.log', var_export(json_encode($uv_new),true), FILE_APPEND); file_put_contents($LOG_PATH . '/uid_new.log', var_export(json_encode($uid_new),true), FILE_APPEND); file_put_contents($LOG_PATH . '/ip_new.log', var_export(json_encode($ip_new),true), FILE_APPEND); file_put_contents($LOG_PATH . '/u_uv.log', var_export(json_encode($u_uv),true), FILE_APPEND); file_put_contents($LOG_PATH . '/su_uv.log', var_export(json_encode($su_uv),true), FILE_APPEND); file_put_contents($LOG_PATH . '/kw_uv.log', var_export(json_encode($kw_uv),true), FILE_APPEND); } file_put_contents($LOG_PATH . '/uv_array.log', var_export(json_encode($uv_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/uid_array.log', var_export(json_encode($uid_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/ip_array.log', var_export(json_encode($ip_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/kw_array.log', var_export(json_encode($kw_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/su_array.log', var_export(json_encode($su_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/u_array.log', var_export(json_encode($u_array),true), FILE_APPEND); file_put_contents($LOG_PATH . '/si_array.log', var_export(json_encode($si_array),true), FILE_APPEND); //记录统计记录完毕 $log_do -> notice(" write analyse data is complete "); //释放变量 if($REDIS_FLAG){ unset($ip_new); unset($uv_new); unset($uid_new); unset($u_uv); unset($su_uv); unset($kw_uv); } unset($uv_array); unset($uid_array); unset($ip_array); unset($kw_array); unset($su_array); unset($u_array); $log_do -> notice(" release var is complete "); flock ( $fp , LOCK_UN); } else { $log_do -> notice(" all.log flock failed "); } fclose ( $fp ); }else{ $log_hour -> error(" No.{$i} all.log fopen error "); exit; } //记录完成 $now = date("Y-m-d H:i:s"); $log_do -> notice(" No.{$i} job done at {$now} "); file_put_contents($LOG_PATH . DIRECTORY_SEPARATOR . 'done.txt', $now . " No.{$i} job is done" . PHP_EOL, FILE_APPEND); $log_hour -> notice(" No.{$i} job done at {$now} "); if(isset($handd0) && true === $handd0){ echo " No.{$i} job done at {$now} "; } }else{ $log_hour -> notice(" No.{$i} alread done "); } }else{ $log_hour -> error(" No.{$i} dir not exist "); }
//处理各级url的通用方法 function reg_u_common_op($u_no){ //引入全局变量 global $a,$u_array,$REDIS_DAY_KEY,$redis,$REDIS_FLAG,$u_uv; if($a[$u_no]){ //记录u,记录后得到每个站点,每个url这段时间的pv数量 /* $u_array = array( '站点一'=>array( 'u1'=>10, 'u2'=>20, ) ) */ isset($u_array[$a[7]][$a[$u_no]]) ? $u_array[$a[7]][$a[$u_no]] += 1 : $u_array[$a[7]][$a[$u_no]] = 1; //记录每个站点,这段时间的u新的uv数量 /* $u_uv = array( '站点一'=>array( 'URL一'=>array( 'uuid1','uuid2' ) ) ) */ if($REDIS_FLAG){ if(!isset($u_uv[$a[7]][$a[$u_no]]) || !in_array($a[19],$u_uv[$a[7]][$a[$u_no]])){ $exist = $redis->HEXISTS("{$REDIS_DAY_KEY}:{$a[7]}:{$a[$u_no]}:U:UV:HASH",$a[19]); if(!$exist){ $u_uv[$a[7]][$a[$u_no]][]= $a[19]; } } } } } exit;
附上nginx的server配置:
server {
listen 80;
server_name 18touch.tongji.com;
index index.php index.html index.htm;
root /home/tongji/webroot;
rewrite ^/h\.js$ /js.php last;
rewrite ^/m\.gif$ /hm.php last;
include global/restrictions.conf;
location ~ \.php$ {
fastcgi_pass php78;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/tongji/webroot$fastcgi_script_name;
include fastcgi_params;
}
location ~ /888/$ {
empty_gif;
fastcgi_pass php78;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/tongji/webroot/hm.php;
include fastcgi_params;
}
}
剩下从redis每日获取昨天的统计数据,然后存储到文本或者mysql。
PS:对目录的操作在win与linux下的函数效果不同,注意文件夹的权限,写文本也有不同。
统计数据从文本返回到php的脚本:
$fp = fopen ('uv_array.log', "r");
while($str = fgets($fp)){
$str = "\$str = " . trim($str,PHP_EOL) .";";
eval($str);
$a = json_decode($str,true);
var_dump($a);exit;
}
|
请发表评论