开发者学堂课程【大数据分析之企业级网站流量运营分析系统开发实战(第二阶段):网站流量日志分析--数据预处理--mr 代码实现】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/694/detail/12189
网站流量日志分析--数据预处理--mr 代码实现
内容介绍
一、 逻辑
二、 重写 web 方法
三、 静态资源过滤
四、 总结
一、 逻辑
1. 首先打开编译器,m码的编写主要就是 map、reduce 还有运行
的组类三个类。
首先写 weblogpreprocess,点击查看,这里主要写了一个内部类 map,还有 main 方法,在预处理过程当中,是没有 reduce 阶段的,所以不需要写。
2. 主要逻辑
(1) 首先写一个静态的内部类,叫 weblogpreprocess,要去继
承编程规范 mapper,确定输入和输出的kv类型。k是 longwritable,v是 text,在进行数据输出的时候,k是输出对象,而v是一个空 nullwritable,所以类型是weblogbean 和 nullwritable。
(2) 创建一个对象,因为这个类型并不是 hadoop 提供的数据类
型,而是自己创建的对象的类型。接下来创建 weblogbean,当中有些属性是不能瞎写的。这在企业当中必须要打开待处理的数据日志并保持一致,一条日志有时间、ip、用户的标识和请求协议,打开笔记,针对数据内容样例有详细的解释,大概用户的访客信息、状态,方式等等各种信息。需要根据这些信息创建对应的私有属性。最后去添加 bool 类型的 valid,判断数据是否合法。
3. 编程技巧
在数据当中,对于非法的数据怎么操作。第一个delete直接删除,就是物理删除;另外一种是创建一个标记位,比如创建一个true or false或者0或者1,这样的判断依据反映的就是逻辑删除。通常使用逻辑删除,便于其他地方使用数据。针对本次分析无效的数据,通常建立标记位的形式进行逻辑删除。
4. 创建好属性之后就可以通过快捷键来生成和构造方法,快捷键是
out+insert,就可以打开constructor构造器,getter and setter方法,tostring,接下来进行相关属性及编辑。这里有两个技术map,第一个,在weblogbean对象当中,重写对象的tostring方法,就是输出打印的样的时候最终底层掉的方法。
这个方法中非常方便的是创建了一个stringbulider,然后把里面的各个字段做了一个拼接,使用\001进行拼接,后面数据输出的时候将会以\001分隔符成为一条记录, \001就是have的默认分割,对于后面数据入库将非常的方便。
这个对象作为m码的自定义对象需要跨网络传递或者持久化操作,所以要实现hadoop的序列化机制叫做wrutable的接口,要去实现两个具体的方法,readfields和write把对应的字段按照apr写入。Weblogbean的编写完成,难度不大,需要细心,主要是根据日志确定对应的字段以及类型。
二、 重写web方法
1. 确定之后回到m码程序当中,核心就是重写对象的web方法。
读一行传一个 kv 对,有用的就是v代表的这一行内容,对完这一行内容大致内容就明确了,把这一行转为字符串进行切割,针对每个字段再做提取,如何进行转换、过滤、格式化、简明等操作。把这一段逻辑单独写一个静态的工具类,叫做weblogparser,里面有个 parser(line)方法,做分装提取。
打开的方法看一下,读取一行,把这一行内容传给工具类的静态方法,方法当中就是预处理的核心逻辑。首先,用一个 weblogbean 对象,然后对数据做切割,需要判断数据当中是什么切割。
2. 空格和字表符看起来都是空白,如何区分
(1) 第一个,可以把这一行内容用写测试的方法来进行切割,比如
以空格或者制表符切割然后看一下继续当中的字段,会不会出现角标越界异常,如果异常的话就是切割出错了;
(2) 第二个方式,使用 notepad++,当中可以显示相关的符号,
选择视图-显示符号-显示空格与制表符,在 notepad++中制表符和空格显示的底层是不一样,放大,如果是空格,它是以点号存在的;如果敲的是制表符,它是以箭头形式存在的,这样就可以从底层看清楚到底是空格还是制表符。一定要做区分不要瞎判断。
接下来回到代码层面切割,完成之后返回字符串的数组,针对这个数组首先做if判断,判断它的长度是不是大于11,为什么要做判断呢,因为数据当中有些记录不满足11个,为什么会有11这个字段呢?仔细数一下,如果数据都完整能达到终端的话至少有12个,如果不满足少于等于12个得到回答的都一样,如果不大于12,数据就会出问题,这里做一个判断看是否大于11,如果不大于11数据肯定是丢失的,直接把对象设置为null;如果满足就把每个属性提出来之后作为对象的设置。
打开数据,数组名arr就是ip;然后是用户的标识;当中主要对时间进行转换,数一下下标,下标三是时间,但是这个时间看起来非常的别扭,首先这个时间的左边有一个中括号,而且这个时间不利于格式理解。
通常是年月日时分表,而这个格式又是数字又是英文非常乱,这里用simpledateformat对时间进行处理。首先取数组的第三个下标,把第一个字段截取下来去掉中括号,去掉之后传给formatdate方法。formatdate是自己定义的方法,在前面定义了两个simpledateformat,第一个是原来的格式,第二个是解析后的格式,通过这两个类做日期格式的转化非常方便。下面就是把对应的字段填写即可,如request、状态码等。
最重要的最后一个字段,叫做用户终端,这个字段的问题在于每条记录的终端长短不一,有的终端字段多,有的终端字段少,字段长短影响很大,因为字段长短不一,导致切割返回的数组长短不一,前面的数组按照顺序填充即可,但最后一个不可以,怎么解决这个问题:将每一条记录按空格进去割,切割的过程中它们的长度长短不一,如下图:
数组长短不一如何解决,这时需要联想到编程技巧,无论最后后面拖了多少,但是从字段的第一个开始一定是固定的,细数一下,一共12个字段,也就是说如果数据要完整的话,是一定要有12个字段,那么12个字段往后的所有数据都是最后一个字段的数据信息明确之后就可以画一个标准,以红线来表示数组字段的长度,字段至少有12个,如果字段大于12、小于12、等于12分别应该怎么办:不足12个字段的意味着数据丢失,属于非法字段;如果字段恰好等于12个,说明最后一个字段就是一个数据就可以;如果大于12了就采用动态拼接,从第12个开始一直到文件的最后,都是最后一个字段的内容,不管多少动态拼接,最后一个动态拼接的内容,无论长短都可以这样做,完美的解决了最后一个字段他本身内容长短导致的数组拼接的问题。
接下来做一个判断,如果数组长度必须大于12,从我们第11位采用动态拼接一直拼接到认识,如果恰好就等于 sb 字段,这里的sb字段就是下标,数组的下标是从零开始的,如果最后一个字段下标恰好是11的话,这个字段最后就作为自己本身,就解决了后面的字段元素较多、拼接麻烦的问题,总结来说就是找出分界线然后分类判断。
其他的如果需要还可以进行相关的过滤,如企业当中状态码大于400的校验码设置为 false,最后返回 weblogbean。
回到程序的主逻辑上,读一条记录,调用方法工具处理返回一个对象,这样就完成了数据的预处理。读取一段内容,在map阶段进行相关格式的转换。
三、 静态资源过滤
这里处理完之后,并没有直接把对象输出去,这里做静态资源过滤,在请求页面的时候,有可能直接请求页面,也有可能直接请求js。针对这些静态资源,如果业务当中需要排除,就做一个非常巧妙的伪装,首先在初始化方法当中创建一个set集合,这个集合中手动写一些路径,这些路径是与企业相关的路径,如果路径不在这些路径下,可能就是其他的非法资源;如果在这些路径下就是合法的。
创建了初始化的方法,在方法里面设置直接路径,把对象传进去,做一个静态资源过滤,把这个集合和对象统一传递给写的方法,拿起对象当中的 request 就开始请求,如果不包含在这个集合当中(前面有感叹号),就把它设置为false,就是请求的路径没有包括这个路径,就是非法数据,把这样的数据设置为 false,这样就完成了静态资源过滤,过滤完之后把对象写出去,v是一个空的类型,预处理操作完成。
整个运处理过程代码在工具类当中,对对象进行切割,字段的转换,判断类型是否超标,是否元素丢失等,这是核心逻辑。
后面的 main 方法就是模板代码,在这里使用本地模式跑一下,看一下预处理操作到底完整不完整。
采用本地模式,输入数据路径在D盘下的weblog\\input
,输出数据在output。然后设置 reducetask 的个数为0,意味着没有 reduce 操作。打开D盘-weblog-input,看一下本地模式能不能处理完成,运行一下,再对程序进行一个编译,那编译完了之后看处理的到底完善不完善。在执行的时候,可以conf康复终端看一下里面执行的日志,如果报错的话,可以发现一些情况,进行相关的处理。
本地模式处理数据是比较快的,打开我们的output,success标明处理成功,part-m是输出性文件,打开来看一下,选择文件右键 editnotepad++,发现数据直观看上去,发现分隔符是空格了,是不可见分隔符\001,这个分隔符对后面的入户处理非常方便,第二个当中的一些字段更新了,因为做了格式统一,数据与修改前的数据一样,只是格式做了修改,就能感觉到日期格式的转换。处理完之后看一下,后面的终端信息也是非常完整的。
通过前面的 true 和 false 来表明数据是否有效,那么搜索一下,当中的false就是无效的数据,true 表示有效的数据,这样就完成了数据的预处理操作。
四、 总结:
本页内容代码比较简单,重点是编程的思路,m码编程中要掌握的就是k是什么,根据k的默认属性把业务迎合它并进行相关的操作即可,要具体梳理,搞清楚怎么样使用代码编程。