用hive或mr清洗app数据
1.项目背景
从大量源数据中清洗出有效数据供后续程序使用。
源数据参照log.txt文件
2.项目源数据说明
9841EF7BDBDF0AC9AF42AEBB4E4F8D4F |
Id |
12 |
状态1 |
22 |
状态2 |
33 |
状态3 |
2013/1/1 23:13:58 |
时间 |
您申请的验证码为541714,有效期10分钟。 <酷狗音乐> |
内容 |
3.项目要求结果
2966127347B2BCD1476B156C377A1969 |
Id |
2013/1/1 |
时间列只要日期,清洗掉时分秒 |
<酷狗音乐>-<酷狗音乐>-[爱聊] |
内容列只要{} [] <> 三种符号之间的内容,并且使用-号连接 |
4. 实现要求
(1).筛出id列、时间列、内容列。以逗号分隔,内容列只要[] {} <> 符号包含的内容,并且以-符号连接
(2).技术要求:mr或者hive实现
源数据:
9841EF7BDBDF0AC9AF42AEBB4E4F8D4F 12 22 33 2013/1/1 23:13:58 您申请的验证码为541714,有效期10分钟。 <酷狗音乐>
03A68484029444218F09098FE159BA1A 12 22 33 2013/1/1 21:10:20 "您的<'天山影城2..>嘀嗒券尾号7539于19时45分消费。客服4000001666。回复“分值#评论”赢积分,分值5最高1最低"
F5AA9052A6D929E8633FC93258794D0F 12 22 33 2013/1/1 23:13:57 恭喜您,爱聊注册成功!还差一步,您就能免费打电话发短信了。请打开 http://m.iicall.com 下载安装软件。[爱聊]
CEE90A5728A3D91E99A16F2D28B5F24F 12 22 33 2013/1/1 23:11:42 尊敬的用户,您本次注册的短信验证码为381663,请及时输入验证码完成注册。<迅雷网络>
93AE376541CC3AD3EC530F7A6872B419 12 22 33 2013/1/1 23:11:41 嘀嗒团:您团购的“子金皇朝酒店1日房”券号570575199105,有效期至1月31日。商家电话地址参考网页
7EBB573A658505AF55C955D860B60DC6 12 22 33 2013/1/1 22:18:06 "亲爱的给惠网会员,恭祝您元旦快乐!合家安康!幸福连连!返利多多!淘宝实时查单,百万年终奖免费送见站内信 geihui.com<给惠网>"
9841EF7BDBDF0AC9AF42AEBB4E5F8D4F 12 22 33 2013/1/1 23:13:58 您申请的验证码为541714,有效期10分钟。 <酷狗音乐>
03A68484029444218F09096FE159BA1A 12 22 33 2013/1/1 21:10:20 "您的<'天山影城2..>嘀嗒券尾号7539于19时45分消费。客服4000001666。回复“分值#评论”赢积分,分值5最高1最低"
F5AA9052A6D929E8633FC98258794D0F 12 22 33 2013/1/1 23:13:57 恭喜您,爱聊注册成功!还差一步,您就能免费打电话发短信了。请打开 http://m.iicall.com 下载安装软件。[爱聊]
CEE90A5728A3D91E99A16F2D28B5F24F 12 22 33 2013/1/1 23:11:42 尊敬的用户,您本次注册的短信验证码为381663,请及时输入验证码完成注册。<迅雷网络>
93AE376541CC3AD3EC53997A6872B419 12 22 33 2013/1/1 23:11:41 嘀嗒团:您团购的“子金皇朝酒店1日房”券号570575199105,有效期至1月31日。商家电话地址参考网页
7EBB573A658505AF55C955D860B60DC6 12 22 33 2013/1/1 22:18:06 "亲爱的给惠网会员,恭祝您元旦快乐!合家安康!幸福连连!返利多多!淘宝实时查单,百万年终奖免费送见站内信 geihui.com<给惠网>"
9841EF7BDBDF0AC9AF42AEBB4E4F8D4F 12 22 33 2013/1/1 23:13:58 您申请的验证码为541714,有效期10分钟。 <酷狗音乐>
03A68484029444218F88098FE159BA1A 12 22 33 2013/1/1 21:10:20 "您的<'天山影城2..>嘀嗒券尾号7539于19时45分消费。客服4000001666。回复“分值#评论”赢积分,分值5最高1最低"
9841EF7BDBDF0AC9AF42AEBB4E4F8D4F 12 22 33 2013/1/1 23:13:57 恭喜您,爱聊注册成功!还差一步,您就能免费打电话发短信了。请打开 http://m.iicall.com 下载安装软件。[爱聊]
CEE90A5728A3D91E66A16F2D28B5F24F 12 22 33 2013/1/1 23:11:42 尊敬的用户,您本次注册的短信验证码为381663,请及时输入验证码完成注册。<迅雷网络>
93AE376541CC7773EC530F7A6872B419 12 22 33 2013/1/1 23:11:41 嘀嗒团:您团购的“子金皇朝酒店1日房”券号570575199105,有效期至1月31日。商家电话地址参考网页
7EBB573A657775AF55C955D860B60DC6 12 22 33 2013/1/1 22:18:06 "亲爱的给惠网会员,恭祝您元旦快乐!合家安康!幸福连连!返利多多!淘宝实时查单,百万年终奖免费送见站内信 geihui.com<给惠网>"
9841EF7BDBDF0A77AF42AEBB4E4F8D4F 12 22 33 2013/1/1 23:13:58 您申请的验证码为541714,有效期10分钟。 <酷狗音乐>
03A68484026666218F09098FE159BA1A 12 22 33 2013/1/1 21:10:20 "您的<'天山影城2..>嘀嗒券尾号7539于19时45分消费。客服4000001666。回复“分值#评论”赢积分,分值5最高1最低"
F5AA9052A6D966E8633FC93258794D0F 12 22 33 2013/1/1 23:13:57 恭喜您,爱聊注册成功!还差一步,您就能免费打电话发短信了。请打开 http://m.iicall.com 下载安装软件。[爱聊]
CEE90A5728A7771E99A16F2D28B5F24F 12 22 33 2013/1/1 23:11:42 尊敬的用户,您本次注册的短信验证码为381663,请及时输入验证码完成注册。<迅雷网络>
93AE376541CC3AD3EC537F7A6872B419 12 22 33 2013/1/1 23:11:41 嘀嗒团:您团购的“子金皇朝酒店1日房”券号570575199105,有效期至1月31日。商家电话地址参考网页
7EBB573A658505AF556655D860B60DC6 12 22 33 2013/1/1 22:18:06 "亲爱的给惠网会员,恭祝您元旦快乐!合家安康!幸福连连!返利多多!淘宝实时查单,百万年终奖免费送见站内信 geihui.com<给惠网>"
9841EF7BDBDF0AC9AF55AEBB4E4F8D4F 12 22 33 2013/1/1 23:13:58 您申请的验证码为541714,有效期10分钟。 <酷狗音乐>
03A68484029444555F09098FE159BA1A 12 22 33 2013/1/1 21:10:20 "您的<'天山影城2..>嘀嗒券尾号7539于19时45分消费。客服4000001666。回复“分值#评论”赢积分,分值5最高1最低"
F5AA9052A6D92555633FC93258794D0F 12 22 33 2013/1/1 23:13:57 恭喜您,爱聊注册成功!还差一步,您就能免费打电话发短信了。请打开 http://m.iicall.com 下载安装软件。[爱聊]
CEE90A5555A3D91E99A16F2D28B5F24F 12 22 33 2013/1/1 23:11:42 尊敬的用户,您本次注册的短信验证码为381663,请及时输入验证码完成注册。<迅雷网络>
93AE376545553AD3EC530F7A6872B419 12 22 33 2013/1/1 23:11:41 嘀嗒团:您团购的“子金皇朝酒店1日房”券号570575199105,有效期至1月31日。商家电话地址参考网页
7EBB573A658505AF55C955D550B60DC6 12 22 33 2013/1/1 22:18:06 "亲爱的给惠网会员,恭祝您元旦快乐!合家安康!幸福连连!返利多多!淘宝实时查单,百万年终奖免费送见站内信 geihui.com<给惠网>"
实现方法:
hive方法:
实现要求
(1).筛出id列(第一列)、时间列(第五列)、内容列(第六列)。以逗号分隔,内容列只要[] {} <> 符号包含的内容,并且以-符号连接
思路:
用hive内置函数:
创建一个字段的表
数据上传到hdfs
hadoop fs -mkdir /source
hadoop fs -put ./log.txt /source
创建外部表
CREATE DATABASE IF NOT EXISTS kugou;
CREATE EXTERNAL TABLE IF NOT EXISTS data(
log String
)
location '/source';
set hive.cli.print.current.db=true;
加载数据
load data inpath '/source/log.txt' into table data;
(1)
第一列数据:筛出id列
split(log,"\t")[0]拆分\t得到第一个字段
select split(log,"\t")[0] from data;
第五列数据:时间列
select split(log,"\t")[4] from data;
第六列数据:内容列
select split(log,"\t")[5] from data;
用逗号分隔;concat
select concat(split(log,"\t")[0],',',split(log,"\t")[4],',',split(log,"\t")[5]) from data;
2013/1/1 时间列只要日期,清洗掉时分秒:
时间列(第五列),以空格拆分,只要第一个字段:
select split(split(log,"\t")[4],' ')[0] from data;
<酷狗音乐>-<酷狗音乐>-[爱聊] 内容列只要{} [] <> 三种符号之间的内容,并且使用-号连接:
思路7:正确
select regexp_extract(split(log,"\t")[5],'(<.*>|\\[.*\\])',1) from data;
合并:以逗号连接
select concat(split(log,"\t")[0],',',split(log,"\t")[4],',',regexp_extract(split(log,"\t")[5],'(<.*>|\\[.*])',1)) from data;
mr方法:
1.
package cn.bcqm1711.mr.sixText.a.m5_31;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
/**
* Created by duqixiang on 2018/5/12.
*/
public class sixTextDemo extends Configured implements Tool {
@Override
public int run(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "sixTextDemo");
job.setJarByClass(sixTextDemo.class);
//mapTask
job.setMapperClass(sixTextMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path("D:\\javaPractice\\work\\log.txt"));
job.setReducerClass(sixTextReducr.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileOutputFormat.setOutputPath(job, new Path("D:\\javaPractice\\out\\out06"));
return job.waitForCompletion(true) ? 0 : 1;
}
public static void main(String[] args) throws Exception {
System.exit(ToolRunner.run(new sixTextDemo(), args));
}
}
2.
package cn.bcqm1711.mr.sixText.a.m5_31;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.jruby.RubyProcess;
import java.io.IOException;
/**
* Created by duqixiang on 2018/5/12.
*/
public class sixTextMapper extends Mapper<LongWritable, Text, Text,Text >{ //输入的数据类型必须是LongWritable
int i = 0;
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//切开数据
String lines = value.toString();
String[] result = lines.split("\t");
String str1 = result[0]; //第1列
String str2 = result[4].split(" ")[0];//第5列,并以空格拆分
String str3 = result[5];//第6列。
String str4 = null; //
if(str3.contains("<")){
str3 = result[5].substring(result[5].indexOf('<'),result[5].indexOf('>')); //substring(起始,最后),不包含最后的字段
str4 = str2 + "," + str3 + ">";
}else if(str3.contains("[")){
str3 = result[5].substring(result[5].indexOf('['),result[5].indexOf(']'));
str4 = str2 + "," + str3 + "]";
}else{
str3 = null;
str4 = str2;
}
System.out.print(str1);
System.out.println(str4);
context.write(new Text(str1),new Text(str4));//以第一列为key,以拼接后的字符串为value
}
}
3.
package cn.bcqm1711.mr.sixText.a.m5_31;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* Created by duqixiang on 2018/5/12.
*/
public class sixTextReducr extends Reducer<Text,Text,Text,Text> {
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
String str2 = null;
String str1 = null;
String str = null;
for (Text n : values) {
String lines = n.toString();
if(lines.contains(",")){ //判断是否有",",是因为部分第六列没有要拼接的内容
String[] result = lines.split(",");//切分成数组
if(str1==null){
str1 =result[1]; //result[1]为最后一列的内容
}else{
str1 = str1 + "-" + result[1];
}
str2 = result[0];
}else{
str2 = lines;
}
}
str = str2 + "\t" + str1;
context.write(key, new Text(str)); //以第一列为key,以拼接后的字符串为value
}
}
自定义UDF函数:
hadoop fs -mkdir /mylog
hadoop fs -put /home/zhaojian/log.txt /mylog
hadoop fs -cat /mylog/log.txt
CREATE external TABLE IF NOT EXISTS log(
id string,
statu1 string,
statu2 string,
statu3 string,
time string,
info string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
stored as textfile
location '/mylog';
//自定义函数.继承UDF.!
add jar /home/zhaojian/myideawork.jar; //添加jar包
CREATE TEMPORARY FUNCTION cons AS 'com.qingmang.udf.MySplit';//创建方法
select concat_ws(",",id,substr(time,0,8),cons(info,"[{<\\[](.*)?[}>\\]]")) from log;//
select concat_ws(",",id,max(substr(time,0,8)),concat_ws("-",collect_list(cons(info,"[{<\\[](.*)?[}>\\]]")))) from log group by id;
//select concat_ws(",",id,max(substr(time,0,8)),collect_set(cons(info,"[{<\\[](.*)?[}>\\]]"))) from log group by id;
collect_set(col) group by 分组之后把同组中的某个字段 放到一个集合,输出,去重
select cons("67677<迅雷网络>asd{rew}21ee[ewd]qwewqe[3213213]567657","[{<\\[](.*?)[}>\\]]");
自定义函数:
package com.qingmang.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MySplit extends UDF {
public String evaluate(String info,String regex){
//把规则编译成模式对象
Pattern p =Pattern.compile(regex);
//通过模式对象得到匹配器对象,存放被匹配的字符串
Matcher m = p.matcher(info);
//这个判断的顺序是从前向后执行,每得到一个正确结果就会停止,判断,等待下次命令再继续执行。
//使用循环
String tot="";
//调用匹配器对象的功能
//通过find方法就是查找有没有满足条件的子串
while(m.find()){
tot += "-"+m.group();
}
if(tot.equals("")) {
return "null";
}else{
return tot.substring(1,tot.length());//索引为0时,字段为"-"
}
//这个破玩意弄了半天!!! 构建路径 后 上传./!! 修改完之后一定要把 新的 传递到 linux 上!! 用新的构建路径!!!
//抛出的各种异常 就会执行不下去!! 所以要在方法里 处理各种可能的情况!!!
}
}