点击流数据:关注的是用户访问网站的轨迹,按照时间来进行先后区分
基本上所有的大型网站都有日志埋点
通过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次
受访升降榜
热点图
用户视图
访问轨迹:从哪个页面跳转到哪个页面等等
访客分析
地区运营商
终端详情
新老访客
忠诚度
活跃度
转化路径分析
分析漏斗模型:
每一步相对于上一步的转化率
每一步相对于第一步的转化率
流量日志分析网站整体架构模块
使用flume来进行采集
使用flume的tailDirSource可以按照正则匹配,收集我们某一个文件夹下面的多个不同类型的数据。
tailDirSource特点:
如果数据这一行数据正在写入,那么过一会儿重试采集,直到数据写入成功a1.sources = r1
a1.pe = 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 channelsink: 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:/
10、访客所用浏览器:Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0
数据的每个字段之间都是用空格隔开的
使用mapreduce来实现
将清洗之后的结构化数据全部load到hive表中
开发数据统计分析的hql的语句
展示我们的结果数据
package cn.itcast.bigdata.weblog.pre;import java.io.IOException;
import java.URI;
SimpleDateFormat;
import java.util.HashSet;
import java.util.Set;import cn.itcast.bigdata.weblog.utils.DateUtil;
import org.f.Configuration;
import org.f.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.bean.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 {@Overridepublic int run(String[] args) throws Exception {//Configuration conf = new Configuration();Configuration conf = Conf();Job job = Instance(conf);/*String inputPath= "hdfs://node01:9000/weblog/"YestDate()+"/input";String outputPath="hdfs://node01:9000/weblog/"YestDate()+"/weblogPreOut";FileSystem fileSystem = (new URI("hdfs://node01:9000"), conf);if (ists(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 = ();/*** 从外部配置文件中加载网站的有用url分类数据 存储到maptask的内存中,用来对日志数据进行过滤*/@Overrideprotected 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/");}@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {String line = String();WebLogBean webLogBean = WebLogParser.parser(line);if (webLogBean != null) {// 过滤js/图片/css等静态资源WebLogParser.filtStaticResource(webLogBean, pages);/* if (!webLogBean.isValid()) return; */k.String());context.write(k, v);}}}public static void main(String[] args) throws Exception {Configuration configuration = new Configuration();int run = ToolRunner.run(configuration, new WeblogPreProcess(), args);it(run);}
}
package cn.itcast.bigdata.weblog.clickstream;import cn.itcast.bean.WebLogBean;
import cn.itcast.bigdata.weblog.utils.DateUtil;
import org.apachemons.beanutils.BeanUtils;
import org.f.Configuration;
import org.f.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.URI;
ParseException;
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 {@Overridepublic int run(String[] args) throws Exception {Configuration conf = Conf();Job job = Instance(conf);/*String inputPath="hdfs://node01:9000/weblog/"YestDate()+"/weblogPreOut";String outputPath="hdfs://node01:9000/weblog/"YestDate()+"/pageViewOut";FileSystem fileSystem = (new URI("hdfs://node01:9000"), conf);if (ists(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\weblogPreOut2"));TextOutputFormat.setOutputPath(job,new Path("file://xxx\pageViewOut2"));job.setJarByClass(ClickStreamPageView.class);job.setMapperClass(ClickStreamMapper.class);job.setReducerClass(ClickStreamReducer.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(WebLogBean.class);job.setOutputKeyClass(Text.class);job.setOutputValueClass(Text.class);boolean b = job.waitForCompletion(true);return b?0:1;}static class ClickStreamMapper extends Mapper<LongWritable, Text, Text, WebLogBean> {Text k = new Text();WebLogBean v = new WebLogBean();@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {String line = String();String[] fields = line.split("