12 网站点击流日志数据分析系统


离线日志的分析综合案例:
第一步:数据的采集 flume,爬虫,javaAPI等等
第二步:数据的统一的存储 hdfs
第三步:数据的清洗 主要目的:将半结构化的数据,转换成结构化的数据 MR来实现 MR比较灵活,可以灵活的处理我们的数据
第四步:数据的映射入库 hive可以将结构化的数据映射成为一张表
第五步:数据的分析 数据仓库DW层,数据的分析
第六步:将分析的结果,存入到hive的临时表当中
第七步:通过sqoop工具将我们的数据导出去到mysql当中
第八步:通过web报表展示工具,展示我们的统计结果

12 网站点击流日志数据分析系统

点击流数据:关注的是用户访问网站的轨迹,按照时间来进行先后区分
基本上所有的大型网站都有日志埋点
通过js的方式,可以获取到你再网站上面点击的所有的链接,按钮,商品,等等,包括你访问的url的链接等等
js埋点,谁来做???专业的前端来做的
埋点收集的数据,都发送到日志服务器 一条日志大概1Kb来算
数据全部在日志服务器
分析用户的点击数据,得到我们的点击流模型

在这里插入图片描述

pageView模型:重视的是每一个页面受到的访问情况,每访问一个页面,就算一条记录
visit模型:重视的是每一个session会话内的访问情况,这次会话内,哪个页面进来,哪个页面出去,进入时间,出去时间

一、网站流量模型分析:

分析的是我们网站流量的来源:

广告推广
自然搜索  百度搜索  google搜索
付费搜索   百度竞价排名
直接流量: 直接敲网站的网址

网站流量多维度的细分:

访问来源:从什么地方来访问的
访问媒介:访问的新老用户,目标页面等等

网站内容分析:

进入网站首页   ==》  商品分类页  ==》 商品详情页 ==》 订单确认页   ==》 付款页面
不怕你不买,就怕你不来  

网站流量转化漏斗分析:
在这里插入图片描述

二、流量常见分析分类:

骨灰级指标

IP:一天之内访问我这个网站不重复IP的个数
一般来说一个IP可能对应多个人


pageView:每打开一个页面,就算一次  pv值
一共访问了多少次页面 

unique  page view:以用户的cookie来为依据,不同的用户对应不同的cookie。一个用户多次访问网站只算一次
去重之后的访问人数 

基础级指标

访问次数:访客从进入网站到离开网站的一系列活动记为一次访问,也称会话(session),1次访问(会话)可能包含多个PV。
网站停留时间:访问者在网站上花费的时间。
页面停留时间:访问者在某个特定页面或某组网页上所花费的时间。

复合级指标

人均浏览页数:平均每个独立访客产生的PV。人均浏览页数=浏览次数/独立访客。体现网站对访客的吸引程度。
跳出率:指某一范围内单页访问次数或访问者与总访问次数的百分比。其中跳出指单页访问或访问者的次数,即在一次访问中访问者进入网站后只访问了一个页面就离开的数量。
退出率:指某一范围内退出的访问者与综合访问量的百分比。其中退出指访问者离开网站的次数,通常是基于某个范围的。

基础分析(PV,IP,UV)

趋势分析:根据选定的时段,提供网站流量数据,通过流量趋势变化形态,为您分析网站访客的访问规律、网站发展状况提供参考。
对比分析:根据选定的两个对比时段,提供网站流量在时间上的纵向对比报表,帮您发现网站发展状况、发展规律、流量变化率等。
当前在线:提供当前时刻站点上的访客量,以及最近15分钟流量、来源、受访、访客变化情况等,方便用户及时了解当前网站流量状况。
访问明细:提供最近7日的访客访问记录,可按每个PV或每次访问行为(访客的每次会话)显示,并可按照来源、搜索词等条件进行筛选。 通过访问明细,用户可以详细了解网站流量的累计过程,从而为用户快速找出流量变动原因提供最原始、最准确的依据。

流量来源分析

主要分析我们的流量从哪些渠道过来的
来源分类
搜索引擎:
搜索词:
最近7日的访客搜索记录
来路域名:
来路页面:
来源升降榜:

受访分析

访问域名  子域名
受访页面:  A.html访问5000次
受访升降榜
热点图
用户视图
访问轨迹:从哪个页面跳转到哪个页面等等

访客分析

地区运营商
终端详情
新老访客
忠诚度
活跃度

转化路径分析

分析漏斗模型:
每一步相对于上一步的转化率
每一步相对于第一步的转化率

三、整体技术流程及架构

流量日志分析网站整体架构模块

1、数据采集模块

使用flume来进行采集
使用flume的tailDirSource可以按照正则匹配,收集我们某一个文件夹下面的多个不同类型的数据。
tailDirSource特点:
如果数据这一行数据正在写入,那么过一会儿重试采集,直到数据写入成功

a1.sources = r1
a1.sources.r1.type = TAILDIR
a1.sources.r1.channels = c1
a1.sources.r1.positionFile = /var/log/flume/taildir_position.json
a1.sources.r1.filegroups = f1 f2
a1.sources.r1.filegroups.f1 = /var/log/test1/example.log
a1.sources.r1.filegroups.f2 = /var/log/test2/.*log.*


channel   memory channel

sink:  hdfs sink   要控制文件的采集的策略,避免hdfs产生大量的小文件
时间长短   文件大小

数据采集过来的字段

1、访客ip地址:   58.215.204.118
2、访客用户信息:  - -
3、请求时间:[18/Sep/2013:06:51:35 +0000]
4、请求方式:GET
5、请求的url:/wp-includes/js/jquery/jquery.js?ver=1.10.2
6、请求所用协议:HTTP/1.1
7、响应码:304
8、返回的数据流量:0
9、访客的来源url:http://blog.fens.me/nodejs-socketio-chat/
10、访客所用浏览器:Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0
数据的每个字段之间都是用空格隔开的

2、数据的清洗|(预处理)

使用mapreduce来实现

3、数据入库

将清洗之后的结构化数据全部load到hive表中

4、数据分析

开发数据统计分析的hql的语句

5、数据的展示

展示我们的结果数据

在这里插入图片描述

四、模块开发----数据预处理

数据预处理

package cn.itcast.bigdata.weblog.pre;

import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;

import cn.itcast.bigdata.weblog.utils.DateUtil;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import cn.itcast.bigdata.weblog.mrbean.WebLogBean;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

/**
 * 处理原始日志,过滤出真实pv请求 转换时间格式 对缺失字段填充默认值 对记录标记valid和invalid
 * 
 */

public class WeblogPreProcess extends Configured implements Tool {
   

	@Override
	public int run(String[] args) throws Exception {
   
		//Configuration conf = new Configuration();
		Configuration conf = super.getConf();
		Job job = Job.getInstance(conf);
		/*String inputPath= "hdfs://node01:9000/weblog/"+DateUtil.getYestDate()+"/input";
		String outputPath="hdfs://node01:9000/weblog/"+DateUtil.getYestDate()+"/weblogPreOut";
		FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:9000"), conf);
		if (fileSystem.exists(new Path(outputPath))){
			fileSystem.delete(new Path(outputPath),true);
		}
		fileSystem.close();
		FileInputFormat.setInputPaths(job, new Path(inputPath));
		FileOutputFormat.setOutputPath(job, new Path(outputPath));
		job.setInputFormatClass(TextInputFormat.class);
		job.setOutputFormatClass(TextOutputFormat.class);
*/
		FileInputFormat.addInputPath(job,new Path("file:///xxx\\input"));
		job.setInputFormatClass(TextInputFormat.class);
		FileOutputFormat.setOutputPath(job,new Path("file:///xxx\\weblogPreOut2"));
		job.setOutputFormatClass(TextOutputFormat.class);
		job.setJarByClass(WeblogPreProcess.class);
		job.setMapperClass(WeblogPreProcessMapper.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(NullWritable.class);
		job.setNumReduceTasks(0);
		boolean res = job.waitForCompletion(true);
		return res?0:1;
	}

	static class WeblogPreProcessMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
   
		// 用来存储网站url分类数据
		Set<String> pages = new HashSet<String>();
		Text k = new Text();
		NullWritable v = NullWritable.get();

		/**
		 * 从外部配置文件中加载网站的有用url分类数据 存储到maptask的内存中,用来对日志数据进行过滤
		 */
		@Override
		protected void setup(Context context) throws IOException, InterruptedException {
   
			pages.add("/about");
			pages.add("/black-ip-list/");
			pages.add("/cassandra-clustor/");
			pages.add("/finance-rhive-repurchase/");
			pages.add("/hadoop-family-roadmap/");
			pages.add("/hadoop-hive-intro/");
			pages.add("/hadoop-zookeeper-intro/");
			pages.add("/hadoop-mahout-roadmap/");

		}

		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
   
			String line = value.toString();
			WebLogBean webLogBean = WebLogParser.parser(line);
			if (webLogBean != null) {
   
				// 过滤js/图片/css等静态资源
				WebLogParser.filtStaticResource(webLogBean, pages);
				/* if (!webLogBean.isValid()) return; */
				k.set(webLogBean.toString());
				context.write(k, v);
			}
		}
	}

	public static void main(String[] args) throws Exception {
   
		Configuration configuration = new Configuration();
		int run = ToolRunner.run(configuration, new WeblogPreProcess(), args);
		System.exit(run);
	}
}

点击流模型pageviews表

package cn.itcast.bigdata.weblog.clickstream;

import cn.itcast.bigdata.weblog.mrbean.WebLogBean;
import cn.itcast.bigdata.weblog.utils.DateUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

import java.io.IOException;
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 
 * 将清洗之后的日志梳理出点击流pageviews模型数据
 * 
 * 输入数据是清洗过后的结果数据
 * 
 * 区分出每一次会话,给每一次visit(session)增加了session-id(随机uuid)
 * 梳理出每一次会话中所访问的每个页面(请求时间,url,停留时长,以及该页面在这次session中的序号)
 * 保留referral_url,body_bytes_send,useragent
 * 
 * 
 * @author
 * 
 */
public class ClickStreamPageView extends Configured implements Tool {
   

	@Override
	public int run(String[] args) throws Exception {
   
		Configuration conf = super.getConf();
		Job job = Job.getInstance(conf);
		/*String inputPath="hdfs://node01:9000/weblog/"+DateUtil.getYestDate()+"/weblogPreOut";
		String outputPath="hdfs://node01:9000/weblog/"+DateUtil.getYestDate()+"/pageViewOut";
		FileSystem fileSystem = FileSystem.get(new URI("hdfs://node01:9000"), conf);
		if (fileSystem.exists(new Path(outputPath))){
			fileSystem.delete(new Path(outputPath),true);
		}
		fileSystem.close();
		job.setInputFormatClass(TextInputFormat.class);
		job.setOutputFormatClass(TextOutputFormat.class);
		FileInputFormat.setInputPaths(job, new Path(inputPath));
		FileOutputFormat.setOutputPath(job, new Path(outputPath));*/

		job.setInputFormatClass(TextInputFormat.class);
		job.setOutputFormatClass(TextOutputFormat.class);
		TextInputFormat.addInputPath(job,new Path("file:///xxx\\weblogP
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值