您的每一次访问wuguangnuo.cn,都会在本站留下足迹:我会获取用户的 USER_AGENT 并将其进行分析应用于我的网站统计中。
网站访客统计
1.数据的获取及存储
除了管理页面中的几个页面外,其余的页面均会在控制器中进行迁至操作
protected function _initialize() {
$Vistor = M('vistor');
$Vistor->create();
$Vistor->lk = $_SERVER['PHP_SELF'];
$Vistor->ip = ip2long(get_client_ip());
$Vistor->ag = $_SERVER['HTTP_USER_AGENT'];
$Vistor->tm = date('Y-m-d H:i:s');
$Vistor->add();
}
采集当前页面链接、用户IP、agent、时间。并将这些信息储存在数据表 wu_vistor 中:
CREATE TABLE IF NOT EXISTS `wu_vistor` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`lk` varchar(255) DEFAULT NULL COMMENT 'link',
`ip` int(4) DEFAULT NULL COMMENT 'ip',
`ag` varchar(255) DEFAULT NULL COMMENT 'agent',
`tm` datetime DEFAULT NULL COMMENT 'datetime',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='访客统计' AUTO_INCREMENT=1;
2.数据的分析
获取到了用户的信息,当然要对这些信息进行分析和统计。在这里用了table表格统计和echert图表统计,其中图表统计中又详细的进行了访客类型、受访页面、操作系统、客户端的分类统计。本文只讨论表格统计的实现。
操作系统统计图
表格中展示了编号、受访页面、IP、地区、ISP、操作系统、浏览器、时间等信息。其中编号、受访页面、IP、时间都在数据库中单独存储,同时也方便读取。
地区和ISP的判定使用了 UTFWry.dat 数据包。入参IP就可以读取更多信息
$Location = new \Org\Net\IpLocation('UTFWry.dat');
foreach($list as &$v) {
$v['ip'] = long2ip($v['ip']);
$v['os'] = get_os($v['ag']);
$v['br'] = get_br($v['ag']);
$v = array_merge($v, $Location->getlocation($v['ip']));
}
get_os 和 get_br 分别是获取操作系统和获取浏览器类型的函数。
这两个函数使用正则表达式来获取系统类型和浏览器类型,例如
if (preg_match('/win/i', $agent) && preg_match('/nt\s*6.1/i', $agent)) {
$os = 'Windows 7';
} else if (preg_match('/win/i', $agent) && preg_match('/nt\s*6.2/i', $agent)) {
$os = 'Windows 8';
} else if (preg_match('/win/i', $agent) && preg_match('/nt\s*10.0/i', $agent)) {
$os = 'Windows 10';
if (stripos($agent, 'Firefox/')) {
preg_match('/Firefox\/([^;)]+)+/i', $agent, $b);
$exp[0] = 'Firefox';
$exp[1] = $b[1]; //获取火狐浏览器的版本号
} else if (stripos($agent, 'Chrome')) {
preg_match('/Chrome\/([\d\.]+)/i', $agent, $google);
$exp[0] = 'Chrome';
$exp[1] = $google[1]; //获取google chrome的版本号
}
这样就获取到了我们所需的全部信息。
这样,再合并分页信息返回就可以展示了
$data['list'] = $list;
$data['pages'] = $p->show();
$this->ajaxReturn($data);
(分页的实现将来会讲)
3.数据的展示
数据展示提供了受访页面筛选,时间区间筛选,展示全部/仅访客/仅蜘蛛,分页等快捷操作。
时间的部分最简单,将用户输入的时间规范化就可以加入到 SQL 语句中查询了。 datetimepicker 插件可以参考我的 demo ,我对其进行了优化。展示范围也比较简单,展示全部就不过滤,仅展示网络蜘蛛就限定ag like '%spider%' or ag like '%bot%',反之则not like。
受访页面部分为了规范化和将来的扩展性,我没有将其写死,而是新建了一张字典表。
![]()
配合 bootstrap-select 插件,就可以正确的获取受访页面,展示文字,同时也兼顾拓展性了。
loadTable 全部代码如下:
public function loadTable($link = null, $date1 = null, $date2 = null, $check = 'all') {
if(!empty($link)){
$arr = explode(',', $link);
$where['lk'] = array('like', $arr, 'or');
}
if(!empty($date1) && !empty($date2)){
if($date1 > $date2){
$date1 = $date1 ^ $date2;
$date2 = $date1 ^ $date2;
$date1 = $date1 ^ $date2;
}
$where['tm'] = array('between',"$date1,$date2");
} else if (!empty($date1)){
$where['tm'] = array('gt',"$date1");
} else if (!empty($date2)){
$where['tm'] = array('lt',"$date2");
}
switch ($check){
case 'bot':
$where['ag'] = array('like',array('%spider%','%bot%'),'OR');
break;
case 'vis':
$where['ag'] = array('notlike',array('%spider%','%bot%'),'AND');
break;
default:
$where['ag'] = array('neq','null');
}
$Vistor = M('vistor');
$count = $Vistor->where($where)->count();
$p = getpage($count, 20);
$list = $Vistor->field(true)->where($where)->order('id desc')->limit($p->firstRow, $p->listRows)->select();
$Location = new \Org\Net\IpLocation('UTFWry.dat');
foreach($list as &$v) {
$v['ip'] = long2ip($v['ip']);
$v['os'] = get_os($v['ag']);
$v['br'] = get_br($v['ag']);
$v = array_merge($v, $Location->getlocation($v['ip']));
}
$data['list'] = $list;
$data['pages'] = $p->show();
$this->ajaxReturn($data);
}