zoukankan      html  css  js  c++  java
  • Hadoop网站日志数据清洗——正则表达式实现

        周旭龙前辈的Hadoop学习笔记—网站日志分析项目案例简明、经典,业已成为高校大数据相关专业的实验项目。上周博主也完成了这个实验,不同于周前辈使用特殊符号切割字符串得到数据的做法,博主使用了正则表达式来匹配数据。在此将我的思路及代码张贴出来,以供后来者学习借鉴。

    一、数据情况分析

        1.1、数据格式概览

            本次实验数据来自于国内某论坛,数据以行为单位,每行记录由5部分组成,访问者IP、访问时间、访问资源、访问状态、访问流量。

        1.2、所需的数据

            按照实验教程,我们只需要IP、时间、uri即可,不过本着既能完成实验,又能锻炼锻炼的想法,我把发个文状态以及访问流量也提取了出来。

        1.3、上传数据至HDFS

            本次试验到手的数据大小为60MB,约60万行。数据量较小,因此直接使用shell命令上传至HDFS。

        注:欲知更详细的项目背景,请点击Hadoop学习笔记—网站日志分析项目案例(一)项目介绍__周旭龙_博客园

        

    二、数据清洗准备

        2.1、日志解析类

            将解析日志信息的功能抽象成为一个日志解析类,分别解析各字段信息。

            2.1.1 各字段的正则表达式

                IP位于行的开头,因此定位到行起始位置,向右读取字符,直到遇到空格。又因为一个有效的IP最少为四个数字+三个符号,7位;最大为3*4+3,15位。所以行起始处7~15位为IP。表达式为:'^S{7,15}'

                时间位于一个方括号内,直接提取方括号内的数据即可:'[.*?]'

                URI及其相关数据与时间数据位置类似,都在成对符号之内,因此可用相同的解法将其提取出来,再做下一步分析:'".*?"'

                状态码只有三位数,且两边都是空格,可以吧两边的空格也提出来,再去掉:' d{3} '

                流量在行尾,也都是数字:'d{1,6}$'

            2.1.2 函数

                除了一个parse函数以及五个分别处理字段的函数外,正则表达式匹配也抽象成了一个函数。需要注意的是匹配是否为空,以及匹配uri并将其分割为数组后下标取值是否越界。

    1. public class parseLine {  
    2.         
    3.     public String[] parse(String line)  
    4.     {  
    5.         String ip = parseIP(line);  
    6.         String time = parseTime(line);  
    7.         String url = parseURL(line);  
    8.         String status = parseStatus(line);  
    9.         String traffic = parseTraffic(line);  
    10.             
    11.         return new String[] {ip,time,url,status,traffic};  
    12.     }  
    13.         
    14.     private String parseReg(String reg,String str)  
    15.     {  
    16.         Pattern pat = Pattern.compile(reg);  
    17.         Matcher matcher = pat.matcher(str);  
    18.         boolean rs = matcher.find();  
    19.         if(rs)  
    20.             return matcher.group(0);  
    21.         else  
    22.             return "null";  
    23.     }  
    24.     
    25.     private String[] splitUrl(String str)  
    26.     {  
    27.         String []urlInfo = str.substring(1, str.length()-1).split(" ");  
    28.         return urlInfo;  
    29.     }  
    30.         
    31.     private String parseTraffic(String line) {  
    32.         String reg_ip = "\d{1,6}$";  
    33.         return parseReg(reg_ip,line);  
    34.     }  
    35.     
    36.     private String parseStatus(String line) {  
    37.         String reg_ip = " \d{3} ";  
    38.         return parseReg(reg_ip,line).trim();  
    39.     }  
    40.     
    41.     private String parseURL(String line) {  
    42.         String reg_ip = "".*?"";  
    43.         String str = parseReg(reg_ip,line);  
    44.         String[] urlInfo = splitUrl(str);  
    45.             
    46.         return urlInfo[1];  
    47.     }  
    48.     
    49.     private String parseTime(String line) {  
    50.         String reg_ip = "\[.*?\]";  
    51.         String str = parseReg(reg_ip,line);  
    52.         SimpleDateFormat in=new SimpleDateFormat("[dd/MMM/yyyy:HH:mm:ss ZZZZZ]",Locale.US);   
    53.         SimpleDateFormat out=new SimpleDateFormat("yyyyMMdd HHmmss");   
    54.         Date d = new Date();  
    55.         try  
    56.         {  
    57.             d=in.parse(str);   
    58.         }  
    59.         catch (ParseException e)  
    60.         {   
    61.             e.printStackTrace();  
    62.         }  
    63.         return out.format(d).trim();  
    64.     }  
    65.     
    66.     private String parseIP(String line) {  
    67.         String reg_ip = "^\S{7,15}";  
    68.         return parseReg(reg_ip,line);  
    69.     }  
    70. }  

        2.2、Mapper类

            map阶段的输入为<偏移量,一行文本>,输出为<偏移量,处理后的数据>。再这个类中,对数据的有效性判断也在这儿,博主只过滤了静态数据。

    1. public class logMap extends Mapper<LongWritable,Text,LongWritable,Text>{  
    2.     static parseInfo parseLine = new parseInfo();  
    3.     protected void map(LongWritable key1,Text value1,Context context) throws IOException,InterruptedException  
    4.     {  
    5.         String str1 = value1.toString();  
    6.         Text output = new Text();  
    7.             
    8.         final String[] info = parseLine.parse(str1);  
    9.             
    10.         if(info[2].startsWith("/static") || info[2].startsWith("/uc_server"))  
    11.             return ;  
    12.     
    13.         StringBuilder result = new StringBuilder();  
    14.         for(String x:info)  
    15.             result.append(x).append(" ");  
    16.             
    17.         output.set(result.toString());  
    18.         context.write(key1, output);  
    19.     }  
    20. }  

        2.3、Reducer类

            reduce阶段的输入与map的输出有关,为<偏移量,处理后数据的集合>,输出则为<处理后的数据,空>。

    1. public class logReducer extends Reducer<LongWritable,Text,Text,NullWritable>{  
    2.     protected void reduce(LongWritable k3,Iterable<Text> v3,Context context) throws IOException,InterruptedException{  
    3.         for(Text v3s : v3)  
    4.             context.write(v3s, NullWritable.get());  
    5.     }  
    6. }  

        2.4、主函数

    1. public class logMain {  
    2.     
    3.     public static void main(String[] args) throws Exception{  
    4.         Job job = Job.getInstance(new Configuration());  
    5.         job.setJarByClass(logMain.class);  
    6.             
    7.         job.setMapperClass(logMap.class);  
    8.         job.setMapOutputKeyClass(LongWritable.class);  
    9.         job.setMapOutputValueClass(Text.class);  
    10.             
    11.         job.setReducerClass(logReducer.class);  
    12.         job.setOutputKeyClass(Text.class);  
    13.         job.setOutputValueClass(NullWritable.class);  
    14.             
    15.         FileInputFormat.setInputPaths(job, new Path(args[0]));  
    16.         FileOutputFormat.setOutputPath(job, new Path(args[1]));  
    17.             
    18.         job.waitForCompletion(true);  
    19.     }  
    20.     
    21. }  

    三、数据清洗

        将编写好的MR到处导出为jar包后,在hadoop中用小规模的测试用例试运行,成功后再用实验数据。

        结果如下:

    注:完整项目

        Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

        Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗

        Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析

  • 相关阅读:
    金融的本质
    读书笔记-关键对话
    pem转pfx
    pem转cer
    Java基础学习总结——Java对象的序列化和反序列化
    Kafka学习之consumer端部署及API
    zookeeper实战:SingleWorker代码样例
    Thread.setDaemon详解
    json对象转换
    【转】Hadoop学习路线图
  • 原文地址:https://www.cnblogs.com/magicxyx/p/10216814.html
Copyright © 2011-2022 走看看