PHP生成网站访问日志
以下两个文件放在根目录 wxylog 文件夹中
wxylog_class.php
<?php
/*
* 生成网站访问日志
* 调用方法:在入口页程序中加入 include('/wxylog/wxylog_class.php'); new wxylog_class();
*/
final class wxylog_class{
private $path='';
private $uri ='';
public function __construct(){
$this->path = dirname(__FILE__).'/log/';
if(!file_exists($this->path) && !mkdir($this->path))return FALSE; //文件夹创建失败
$this->uri = $this->server('REQUEST_URI');
if(! $this->allow())return FALSE; //是否需要记录
$this->log();
}
private function server($para){
$para = strtoupper($para);
return isset($_SERVER[$para]) ? str_replace(chr(9), chr(32), $_SERVER[$para]) : '';
}
private function log(){
$file = $this->path.date('Ymd').'.log';
$str = date('Y-m-d H:i:s');
foreach(array('REMOTE_ADDR', 'REQUEST_METHOD', 'REQUEST_URI', 'HTTP_USER_AGENT', 'HTTP_REFERER') as $item){
$str .= chr(9).$this->server($item);
}
$str .= "\n";
//写入访问日志
@file_put_contents($file, $str, FILE_APPEND);
//获取蜘蛛类型
$array = array('Baiduspider', 'Sogou web spider', 'Googlebot', 'bingbot', 'Sosospider', 'yisouspider', 'Yahoo! Slurp', '360Spider');
$robot = '';
foreach($array as $item){
if(strpos(strtolower($this->server('HTTP_USER_AGENT')), strtolower($item)) !== FALSE){
$robot = $item;
break;
}
}
$file = $this->path.date('Ymd').'.php';
$array = @include $file;
is_array($array) OR $array=array('total'=>0, 'not_robot'=>0, 'robot'=>array(), 'request_method'=>array(), 'page'=>array('index'=>0, 'inside'=>0, 'http_referer'=>0)); //访问总数、非蜘蛛访问数、各蜘蛛访问数、受访页面(首页、内页、通过其他链接进入)
//访问总数
$array['total'] += 1;
//请求方式
if($method = $this->server('REQUEST_METHOD')){
isset($array['request_method'][$method]) OR $array['request_method'][$method]=0;
$array['request_method'][$method]+=1;
}
//首页/内页访问数
$array['page'][preg_match('/^\/(index.php)?(\/?\?.+)?$/i', $this->uri) ? 'index' : 'inside'] += 1;
//通过其他链接进入数
$this->server('HTTP_REFERER') AND $array['page']['http_referer'] += 1;
//更新蜘蛛访问数
if($robot){
isset($array['robot'][$robot]) OR $array['robot'][$robot]=0;
$array['robot'][$robot]+=1;
}else{
$array['not_robot'] += 1;
}
$code = "<?php\n return ". var_export($array, true) .";\n";
//写入统计
@file_put_contents($file, $code);
//禁止访问某些页面
$this->deny($robot);
}
//禁止访问某些页面,根据实际需要单独开发
private function deny($robot){
//比如禁止百度访问搜索页
//if(strpos($this->uri, 'search')!==FALSE && $robot=='Baiduspider')exit('ACCESS DENIED');
}
//是否记录当前uri,根据实际需要单独开发
private function allow(){
/*
//比如不记录验证码生成程序
//以下均为正则表达式
$array = array(
'\/verifycode'
);
foreach($array as $item){
if(preg_match('/^\/(index.php)?'.$item.'/i', $this->uri))return FALSE;
}
*/
return true;
}
}
wxylog_view.php
<?php
/*
* 日志查看程序 wxy 20180106
* 当前页面必须放在 /wxylog 目录下
* /wxylog/wxylog_class.php 在入口页程序中加入以下代码调用: include('/wxylog/wxylog_class.php'); new wxylog_class();
* /wxylog/wxylog_view.php
* 自动生成的其他日志文件,以年月日8位数字开头。如 20180106.log, 20180106.php
*/
define('LOG_PATH', dirname(__FILE__).'/log/');
switch($_SERVER['REQUEST_METHOD']){
case 'GET':
if(! isset($_COOKIE['wxylog']) || $_COOKIE['wxylog'] !== 'ok'){
show_login();
exit;
}
if(isset($_GET['date'])){ //获取日志详情
show_log();
}else{
show_list(); //显示列表
}
break;
case 'POST':
if(isset($_POST['pwd']) && sha1($_POST['pwd'])==='59b331507615f9f98bf17558ee678cafdbdb5bfe'){
setcookie('wxylog', 'ok');
header('Location: '.$_SERVER['REQUEST_URI']);
exit;
}elseif(isset($_POST['date'])){
delete_log();
}
break;
default:
exit('ACCESS DENIED');
}
function show_log(){
$date = $_GET['date'];
if(! preg_match('/^20\d{6}$/', $date))exit('');
echo '<pre style="font:14px/1.5 Arial;">';
exit(@file_get_contents(LOG_PATH.$date.'.log'));
}
function show_data(){
$array = @scandir(LOG_PATH, 1);
if(! $array)return FALSE;
foreach($array as $file){
if(is_dir($file) || !preg_match('/^20\d{6}\.php$/', $file))continue;
$data = @include LOG_PATH.$file;
is_array($data) AND echo_html($file, $data);
}
}
function format_bytes($size, $delimiter = '') {
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
return round($size, 2) . $delimiter . $units[$i];
}
function delete_log(){
$date = $_POST['date'];
if(preg_match('/^20\d{6}$/', $date)){
if(@unlink(LOG_PATH.$date.'.log')){
exit(@unlink(LOG_PATH.$date.'.php') ? 'success' : 'fail');
}else{
exit('fail');
}
}else{
exit('ACCESS DENIED');
}
}
function echo_html($file, $data){
if(! isset($data['total']))return;
$date = substr($file,0,8);
echo '<div class="col-sm-4 col-md-3"><ul class="list-group"><li class="list-group-item active"><strong>', $date, '</strong><div class="pull-right"><a href="javascript:;" data-del-file="', $date, '">删除</a> <a target="_blank" href="?date=', $date, '">浏览</a></div></li>';
echo '<li class="list-group-item">访问次数 <kbd>', $data['total'], '</kbd></li>';
echo '<li class="list-group-item">搜索引擎 <kbd>', $data['total']-$data['not_robot'], '</kbd></li>';
echo '<li class="list-group-item">正常访问 <kbd>', $data['not_robot'], '</kbd></li>';
echo '<li class="list-group-item list-group-item-success"><strong>访问页面</strong></li>';
echo '<li class="list-group-item">首页 <kbd>', $data['page']['index'], '</kbd></li>';
echo '<li class="list-group-item">内页 <kbd>', $data['page']['inside'], '</kbd></li>';
echo '<li class="list-group-item">通过其他链接访问 <kbd>', $data['page']['http_referer'], '</kbd></li>';
echo '<li class="list-group-item list-group-item-info"><strong>请求方式</strong></li>';
arsort($data['request_method']);
foreach($data['request_method'] as $key=>$val){
echo "<li class=\"list-group-item\">{$key} <kbd>{$val}</kbd></li>";
}
if($data['total'] != $data['not_robot']){
echo '<li class="list-group-item list-group-item-warning"><strong>搜索引擎</strong></li>';
arsort($data['robot']);
foreach($data['robot'] as $key=>$val){
echo "<li class=\"list-group-item\">{$key} <kbd>{$val}</kbd></li>";
}
}
echo '<li class="list-group-item list-group-item-danger">日志文件 <kbd>', format_bytes(filesize(LOG_PATH.$date.'.log')), '</kbd></li>';
echo '</ul></div>';
}
function show_list(){
?><!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>数据统计</title>
<link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" rel="stylesheet">
<style>
body,kbd{font-size:medium;}
a{color:#bce8f1;}
.container{padding-top:20px;}
</style>
</head>
<body>
<div class="container">
<div class="row">
<?php show_data(); ?>
</div>
</div>
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$('a[data-del-file]').click(function(){
if(!confirm('确定要删除此日志吗?'))return;
$.post('', {date:$(this).attr('data-del-file')}, function(text){
if(text=='success'){
alert('删除成功');
self.location.reload();
}else{
alert('删除失败');
}
}, 'text');
});
</script>
</body>
</html>
<?php
}
function show_login(){
?><!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Log System</title>
<link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" rel="stylesheet">
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
body{background:#333;}
a{font-size:large !important;cursor:pointer;}
.mybox{margin:0 auto;width:300px;}
</style>
</head>
<body>
<div class="mybox">
<form class="form-inline" method="post">
<div class="form-group form-group-lg">
<div class="input-group">
<input type="password" name="pwd" class="form-control" placeholder="password" autocomplete="new-password" autofocus>
<a class="input-group-addon" onclick="$('form')[0].submit()">Login</a>
</div>
</div>
</form>
</div>
<script>$('.mybox').css('margin-top', $(window).height()/3);</script>
</body>
</html>
<?php
}
