> 文章列表 > 九耶丨钛伦特-教你使用Java语言清洗京东商品数据

九耶丨钛伦特-教你使用Java语言清洗京东商品数据

九耶丨钛伦特-教你使用Java语言清洗京东商品数据

       数据清洗是数据处理的前奏,也是数据处理的关键所在。使用java语言通过mapreduce技术可以实现数据清洗,一般对日志类型的数据会进行这样的清洗。

       数据的清洗主要需要处理的是数据的过滤,重在三步走,去重,去空,去异常。

       具体操作使用步骤如下。

        1、使用IntelliJ IDEA新建项目。

      ​2、这里通过maven技术实现项目数据的清洗。

     ​3、接下来添写大数据开发需要的hadoop相关的groupId或artifactId。

     ​4、点击“Next”进入下一步,接下来的窗口参数默认。点击Finish完成

     ​5、使用maven技术开发项目,需要指定相关依赖。

​       这里的程序Mapper,Ruducer,Job,一定要注意json数据是值对,值对有JavaBean对应。

       值对就是面向对象,面向对象就是一个属性一个值,json数据就是一个属性一个值。json对应java对象。遇到json一定有JavaBean。

        注意企业中常见的问题就是wordcount的问题,即在项目中统计文档中英文出现的个数,如英文单词 hadoop的个数,结合到企业中的分析,如一天内用户点击率有多少,把用户点击率当成word,然成求count,只要清楚哪一列是用户点击率。

        下面进入开发的步骤,需要建立JavaBean,JavaBean作用让你知道每一列到底是何意义。

         第一步:建立一个GoodsBean,建立之后数据有意义。

        ​第二步:把GoodsBean里面Json对应的属性全部写入 。

        注意:price为什么在Bean中定义成String,它是Float型,我们要做的事是清洗,去空,如果抓取的price为空,这个地方显示空,如果是Float,这个地方显示的是0。爬虫爬取的时候,一般原生数据直接爬取,是空的可能性比是0的可能性大。尤其对爬虫来说不是写代码,比如八爪鱼这类类似于爬虫的工具,这个不需要写代码。这里就把price做字符串处理。后续导入hive时没有空数据,没有空数据就可以作Float。

       定义完属性后,代码如下:

​        定义getter和setter 方法,为了面向对象的封装道理,因为私有属性,做取数据和设置数据的接口。

       在代码处右键,选择”Generate....”

       点击”Generate....”,选择getter和setter

       把所有的属性都做一个getter和setter方法

​       点击”Ok”即可。

       习惯性地构造两个方法,也就是构造函数,第一个方法无参,为了方便,第二个方法全参。全参目的是应对linux中每一列的意义是从另一个文件中给出的,不是一个json数据,类似于json数据。在公司项目上的合作,大部分都是json数据合作。

        在公司中,处理的大数据都是多维度的,有可能达到100列,200列,多类型,最后才是大的数据量。这里产生无参构造器和有参构造器,这是完成JavaBean的步骤所在。

        在代码处右键,选择”Generate....”。

       构造一个无参构造器。

        ​点击弹出框所有属性,结合shift键,作全参构造器。

​      这样GoodsBean 的代码如下。

        写Mapper方法,继承于Mapper,注意输入,输出的类型,在Mapper中输入只能是LongWritable,Text,因为LongWritable是行号,Text是内容,不是String是因为String的序列化就是Text。序列化原因是两个电脑需要传输数据。再注意输出的类型,maper方法的输出会输出<hadoop,1>,<word,1>,这里想,<json数据1,1>,<json数据2,1>,得出输入的第一个参数是Text,也就是文本,第二个参数就是整数,整数的序列化是IntWritable;

       然后在类代码中右键,选择override,即重写的是map方法。

      在接下来的弹出对话框中选择map方法。

        选择完点击 “OK”即可。

        写map的逻辑,在mapper中读取每一行,之后json化数据,判断空数据和判断异常数据,这里的异常是comment_sum中不可以有“万”和”+”。

        “万”替换成为”0000”,“+”替换成 空。

        现在没有进行清洗处理,为了调试程序的方便,直接把 mapper 的输出写完。

​       再写GoodsReudcer ,写继承于Reducer。输入是上一级的 Mapper的输出,希望的输出是<json数据>,reduce方法必须输入值对,后面的值就是NullWritable;

       写reducer中的逻辑实现

       首先重写reduce方法

​       在reduce方法中不统计,直接输出。

        下面写goodsJob,相当于调用mapreduce的主程序

​       执行一遍,mapper输出的空是True还是false;

       注意,执行时如果报错,可能是下列原因,一般情况下目录存在。

       打印的信息如果显示

​      没有重写 toString()方法,重写 toString()

      仔细找一下,有一个显示True的,

​       找到对应的输出方法

       只有goods.getPublisher().length()==0是有true,其它空的都显示false,判断逻辑是有问题。

       这样,就实现了mapreduce来使用去重去空去异常对 json数据进行清洗。

       注意:麻烦的地方,在goodsBean里面一 定设置变量。

       公司里面变化的数据,如果有20个维度,30个维度,Bean里面代码成倍增长。修改一个属性,比如原来是publisher,后来变成author,那会带来很大的麻烦。

​       这种尺度很难把握。引入lombok类。帮助我们产生getter, setter方法,还有构造器,toString()。

       添加完这个依赖后,直接就把GoodsBean作修改。因为getter或者是setter会因为变量的变化而变化,这里引入lombok来解决这个问题,不过plugin中也需要安装插件。

       在左边选择plugins,右边输入查询lombok

       然后在Bean类中加入一个注解,注解就是lombok中的Data注解,注解帮助我们解决getter和setter及构造器。

       这种类形的类,setter有了,getter有了,构造器有了,toString()方法也有了。

​       

       重写toString()方法,因为在mapper 里调用的toString()方法。

​       最后形成如下代码:

       以上注意是采用把对象toString()变成文本,然后利用Text类型进行序列化的。

       在百度上面搜索相关的Text序列化的清洗方法,会发现清洗方法是把对象实现WritableComparable接口。实现了看一下。

​       实现接口后,是红线,红线表示有些方法没有被重写。

       看一下介绍内容,每个维度都要写一遍

       再看readFile方法

       发现代码中getter和setter方法仍然有。

       如果维度多,你就要一个一个write,然后再readFile。不利于代码维护,数据库的定义在项目初期考虑内容不全面,后期由于用户功能修改,添加维度,意味着模型要添加数据,大数据分析需求再修改,又会添加某些维度,添加维度后,json数据是永远的课题,使一个类简单的处理应付变化的需求,所以采用Text序列化一个Bean类。

       实现这个接口WritableComparable,reduce的逻辑重新建立。

       把javaBean实现序列化。

       这里也需要getter和setter方法,建议使用lombok,lombok没有起到序列化的作用。

​       对Mapper进行修改。

       首先对类型进行修改,因为GoodsBean已经序列化,不需要输出Text,需要输出GoodsBean;

​       第二因为GoodsBean已经序列,原来使用Text就可以去掉。

       Reducer需要修改,同样修改类型,输入和输出都要修改类型。

       对应最后的主程序也要修改。

       运行之后看结果。

       Java的MapReduce有错误,基本没有输出结果。

​       看运行结果没有错误显示,没执行,这里把GoodsBean换成GoodsBeanXuLie

       Mapper方法中改动的地方

​       Reducer方法的改动的地方:

​       最后的Job需要改动的地方.

       再执行一遍,看问题。

       从结果上看,mapper都执行,查是打印==的reduce只有一行。

​       就是Reduce只执行了一次,需要执行多次,将所有map输出的values形成的叠代器遍历。去打印key值。

​        这种迭代没有去重。去重,计数式的统计。Reduce的逻辑复杂。

       通过结果,看到结果还电带上了一对象名,也不是纯的json结果。还需要javabean重写toString()的方法。

       继承的WritableComparable,必须重写write和readFile。同时还需要重写类中的toString()方法才能输出正确的json数据。这是实现WritableComparable接口实现的数据清洗序列化手段。