文章目录
- 7-点击流数据分析项目-数据预处理
- 1.数据集介绍
- 原始数据样式:
- 待生成的页面点击流模型Pageviews表
- 待生成的点击流模型Visits表
- 数据清洗
- 2.采集日志数据到HDFS上
- 创建目录
- 编写脚本
- 脚本内容
- 给脚本添加执行权限
- 执行脚本
- 3.采用MR实现数据预处理-过滤静态资源
- 创建maven工程
- 编写日志的实体类
- 编写处理数据清洗的工具类
- 编写预处理Mapper类
- 编写预处理Driver类
- 4.采用MR实现数据预处理-获得页面流pageviews数据模型
- pageviews原理
- 创建页面流数据模型pageviews-Mapper类
- 创建页面流数据模型pageviews-Reducer类
- 创建页面流数据模型pageviews-Driver类
- 5.采用MR实现数据预处理-获得点击流访问表visits数据模型
- 点击流访问表visits原理
- 生成点击流访问数据
- 生成Visits访问数据MR-实体类PageViewsBean
- 生成Visits访问数据MR-实体类VisitBean
- 生成Visits访问数据MR-Mapper类ClickStreamVisitMapper
- 生成Visits访问数据MR-Reducer类ClickStreamVisitReducer
- 生成Visits访问数据MR-Driver类ClickStreamVisitDriver
- 导入HDFS
- 总结
- 1.数据集介绍
7-点击流数据分析项目-数据预处理
1.数据集介绍
数据集介绍见https://blog.csdn.net/m0_38139250/article/details/122181337
数据集下载地址:
https://download.csdn.net/download/m0_38139250/72088781
中,我们对项目做了大致的介绍,这里摘录数据的部分罗列如下:
原始数据样式:
194.237.142.21 - - 18/Sep/2021:06:49:18 0000 “GET /wp-content/uploads/2013/07/rstudio-git3.png HTTP/1.1” 304 0 “-” “Mozilla/4.0 (compatible;)”
待生成的页面点击流模型Pageviews表
session为一个用户,用户对网站的每次访问。
待生成的点击流模型Visits表
(按session聚集的页面访问信息)
这就是点击流模型。当WEB日志转化成点击流数据的时候,很多网站分析度量的计算变得简单了,这就是点击流的“魔力”所在。基于点击流数据我们可以统计出许多常见的网站分析度量
数据清洗
- 时间格式无效
- 响应状态码》400
- 静态页面删除(js、css资源)
2.采集日志数据到HDFS上
创建目录
代码语言:javascript复制# 创建 /sx/clickstream/process/input 目录
hadoop fs -mkdir -p /sx/clickstream/process/input
编写脚本
代码语言:javascript复制touch mv2clickstreamprocessinput.sh
脚本内容
代码语言:javascript复制#!/bin/bash
#
# ===========================================================================
# 程序名称:
# 功能描述: 移动文件到预处理工作目录
# 输入参数: 运行日期
# 目标路径: /sx/clickstream/process/input
# 数据源 : /home/ubuntu/Code/sx
# 代码审核:
# 修改人名:
# 修改日期:
# 修改原因:
# 修改列表:
# ===========================================================================
#lsn上传日志文件存放的目录
log_dir=/home/ubuntu/Code/sx
# 日志文件名字
log_name=access.log.fensi
#预处理程序的工作目录
log_pre_input=/sx/clickstream/process/input
#读取日志文件的目录,判断是否有需要上传的文件
#files=`hadoop fs -ls $log_dir | grep $day_01 | wc -l`
files=`ls $log_dir | wc -l`
hadoop fs -mkdir -p ${log_pre_input}
if [ $files -gt 0 ]; then
hadoop fs -put ${log_dir}/${log_name} ${log_pre_input}
echo "success moved ${log_dir}/${log_name} to ${log_pre_input} ....."
fi
给脚本添加执行权限
代码语言:javascript复制chmod u x mv2clickstreamprocessinput.sh
chmod是权限管理命令change the permissions mode of a file的缩写。。
u代表所有者,x代表执行权限。 表示增加权限。
chmod u x file.sh 就表示对当前目录下的file.sh文件的所有者增加可执行权限。
执行脚本
代码语言:javascript复制sh mv2clickstreamprocessinput.sh
3.采用MR实现数据预处理-过滤静态资源
创建maven工程
修改pom文件
代码语言:javascript复制 <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>1.1.2</version>
<!-- <version>1.2.3</version> -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>com.mystudy.hadoopPro.APP</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<!-- 可以打 fat 和thin jar-->
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
回顾下原始数据:
194.237.142.21 - - 18/Sep/2021:06:49:18 0000 “GET /wp-content/uploads/2013/07/rstudio-git3.png HTTP/1.1” 304 0 “-” “Mozilla/4.0 (compatible;)”
编写日志的实体类
edu.sx.clickstream.pre.WebLogBean
代码如下
代码语言:javascript复制package edu.sx.clickstream.pre;
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* 对接外部数据的层,表结构定义最好跟外部数据源保持一致
* 术语: 贴源表
* @author
*
*/
public class WebLogBean implements Writable {
private boolean valid = true;// 判断数据是否合法
private String remote_addr;// 记录客户端的ip地址
private String remote_user;// 记录客户端用户名称,忽略属性"-"
private String time_local;// 记录访问时间与时区
private String request;// 记录请求的url与http协议
private String status;// 记录请求状态;成功是200
private String body_bytes_sent;// 记录发送给客户端文件主体内容大小
private String http_referer;// 用来记录从那个页面链接访问过来的
private String http_user_agent;// 记录客户浏览器的相关信息
public void set(boolean valid,String remote_addr, String remote_user, String time_local, String request, String status, String body_bytes_sent, String http_referer, String http_user_agent) {
this.valid = valid;
this.remote_addr = remote_addr;
this.remote_user = remote_user;
this.time_local = time_local;
this.request = request;
this.status = status;
this.body_bytes_sent = body_bytes_sent;
this.http_referer = http_referer;
this.http_user_agent = http_user_agent;
}
public String getRemote_addr() {
return remote_addr;
}
public void setRemote_addr(String remote_addr) {
this.remote_addr = remote_addr;
}
public String getRemote_user() {
return remote_user;
}
public void setRemote_user(String remote_user) {
this.remote_user = remote_user;
}
public String getTime_local() {
return this.time_local;
}
public void setTime_local(String time_local) {
this.time_local = time_local;
}
public String getRequest() {
return request;
}
public void setRequest(String request) {
this.request = request;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getBody_bytes_sent() {
return body_bytes_sent;
}
public void setBody_bytes_sent(String body_bytes_sent) {
this.body_bytes_sent = body_bytes_sent;
}
public String getHttp_referer() {
return http_referer;
}
public void setHttp_referer(String http_referer) {
this.http_referer = http_referer;
}
public String getHttp_user_agent() {
return http_user_agent;
}
public void setHttp_user_agent(String http_user_agent) {
this.http_user_agent = http_user_agent;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
/**
* 01是hive当中默认的分隔符,不会出现用户手打出来的情况
* @return
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.valid);
sb.append("