网站统计数据

网站的统计数据有很多个,其中比较重要的是PV(Page View)、UV(Unique View)、页面停留时间、网站访问时间。

PV:指网站的页面浏览量,每刷一次页面,算一次

PV:指网站的独立访客数,同一个IP在同一天的多次访问只算一次。

页面停留时间:指用户在页面上停留的时间

网站访问时间:指用户退出网站时间与用户进入网站的时间差

 

其中页面停留时间的统计有多种方法

1、定时刷新后台

打开页面后,每隔一段时间刷新后台,以第一次刷新和最后一次刷新的时间差作为页面停留时间,同时设置最大页面停留时间。

优点:统计的页面停留时间相对比较准确。

缺点:当网站的访问量上来后,这种方式有很大的代价,后台日志的负载会非常大。

2、计算两个页面的访问时间差

比如T1时刻访问页面P1,T2时刻访问页面P2,那么访问页面P1的时间T=T2-T1,但访问最后一个页面的时间为0。

优点:统计方式比较简单明了。

缺点:统计的结果可能不太准确,比如打开P1页面后,再打开P2页面,然后再返回P1页面,这时统计的结果就不准确。

3、通过鼠标的滑动来刷新后台

当页面有鼠标的滑动时,就向后台刷新日志,以第一次滑动和最后一次滑动的时间差当作页面停留时间。

优点:统计的页面停留时间比较准确

缺点:后台日志的负载会比较大

 

下面用Java+Spring+Mysql实现第二种方式的统计

1、项目的程序结构如下:

网站统计数据_第1张图片

2、核心代码

2.1 日志拦截器LogFilter.java

package com.filter;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.bean.LogBean;
import com.service.LogService;

public class LogFilter implements Filter {

	Logger logger = Logger.getLogger(LogFilter.class);

	@Autowired
	private LogService logService;
	
	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		if (!(servletRequest instanceof HttpServletRequest)
				|| !(servletResponse instanceof HttpServletResponse)) {
			throw new ServletException(
					"OncePerRequestFilter just supports HTTP requests");
		}
		
		HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
		HttpSession session = httpRequest.getSession();
		String ip = httpRequest.getRemoteAddr();          
		String page = httpRequest.getRequestURI();
		String contextPath = httpRequest.getContextPath();
		String servletPath = httpRequest.getServletPath();
		
		logger.info("doFilter sessionId="+session.getId()+",ip="+ip+",page="+page+",contextPath="+contextPath+",servletPath="+servletPath);
		
		LogBean  logBean = new LogBean();
		logBean.setId(UUID.randomUUID().toString());
		logBean.setSessionId(session.getId());
		logBean.setIp(ip);
		logBean.setPage(page);
		logBean.setAccessTime(new Timestamp(new Date().getTime()));
		logBean.setStayTime(0);
		
		//通过session id 和 ip,查出最近的一条访问记录
		LogBean bean = null;
		try {
			bean = logService.getLatestLog(session.getId(), ip);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		
		//更改最近访问记录的停留时间,这里把两次访问记录的间隔时间算成上一次页面访问的停留时间
		if(bean != null){
			long stayTime = (System.currentTimeMillis() - bean.getAccessTime().getTime())/1000;
			try {
				logService.updateLog(bean.getId(), stayTime);
			} catch (Exception e) {
				e.printStackTrace();
				logger.error(e.getMessage());
			}
		}
		
		//保存当前访问记录
		try {
			logService.saveLog(logBean);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		
		//统计网站今天的PV(页面浏览量),UV(独立访客数)
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		String format = df.format(new Date());
		Date parse = null;
		try {
			parse = df.parse(format);
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		
		Timestamp startTime = new Timestamp(parse.getTime());
		Timestamp endTime = new Timestamp(parse.getTime() + 24*3600*1000);
		try {
			int pv = logService.getPV(startTime, endTime);
			int uv = logService.getUV(startTime, endTime);
			logger.info("pv="+pv);
			logger.info("uv="+uv);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		
		filterChain.doFilter(servletRequest, servletResponse);
		return;
	}

	
	public void init(FilterConfig filterConfig) throws ServletException {
		 ServletContext context = filterConfig.getServletContext();  
		 ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);  
		 logService = (LogService) ctx.getBean("logService");
		 logger.info("init");
	}

	
	public void destroy() {
	}
}

2.2 web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<context-param> 
    	<param-name>contextConfigLocation</param-name> 
    	<param-value>/WEB-INF/classes/applicationContext.xml</param-value> 
  	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<filter>
		<filter-name>logFilter</filter-name>
		<filter-class>com.filter.LogFilter</filter-class>
	</filter>
	
	<filter-mapping>
		<filter-name>logFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
    
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
</web-app>
 
 

3、日志表设计

CREATE TABLE log ( 
    id         	varchar(64) NOT NULL,
    session_id 	varchar(64) NOT NULL,
    ip         	varchar(64) NULL,
    page       	varchar(200) NULL,
    access_time	timestamp NULL,
    stay_time  	mediumtext NULL,
    PRIMARY KEY(id)
)
ENGINE = InnoDB
AUTO_INCREMENT = 0
;
CREATE INDEX log_index
    ON log(session_id, ip)
;

4、项目的下载地址如下

http://download.csdn.net/detail/brushli/7518709

5、评价与展望

该系统的设计能基本满足中小网站的数据统计,对于对准确性要求比较高的网站来说,关键统计数据的统计方法应做改进;

对于并发量比较高的网站来说,直接将日志插入数据库的方式也应做改进,比如改用消息队列MQ来处理。


 

 

 

你可能感兴趣的:(pv,UV,页面停留时间,网站访问时间)