MapReduce数据去空去重进阶版及数据乱码解决方法

3 篇文章 0 订阅
2 篇文章 0 订阅

前言

之前写过一篇MapReduce对CSV文件去空去重,虽然能实现功能但是还有很多地方需要改进,刚好有新爬好的智联招聘的职位信息,所以再来一遍,爬取智联招聘的代码链接https://blog.csdn.net/weixin_42063239/article/details/88524079

这里只对职位名称或职位描述字段为空的数据删除,因为爬出来的数据比较规范没有空值和重复值,可以自己人为制造一些不符合规范的数据

话不多说上代码,改进了的地方在代码后列出,详细注释上一篇有就不写了,链接https://blog.csdn.net/weixin_42063239/article/details/88315036

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class Zhilian {
    
    public static Text nullData = new Text("");
    public static Text text = new Text("");
    public static class Map extends Mapper<Object, Text, Text, Text>{

        public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();
            if(isRightData(line)){
                String data = line.replace(",", "|");
                text.set(data);
                context.write(text, nullData);
            }

        }
        //只判断职位名称和职位描述是否为空
        boolean isRightData(String line){
            Boolean flag = true;
            String[] items = line.split(",");
            if(items[7].trim().isEmpty() || items[8].trim().isEmpty()){
                flag = false;
            }
            return flag;
        }
    }


    public static class Reduce extends Reducer<Text, Text, Text, Text> {
        public void reduce(Text key, Iterable<Text> value, Context context) throws IOException, InterruptedException {
            context.write(key, nullData);
        }
    }



    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration conf = new Configuration();
        Job job = Job.getInstance();
        job.setMapperClass(Map.class);
        job.setCombinerClass(Reduce.class);
        job.setReducerClass(Reduce.class);
        job.setJarByClass(Zhilian.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);

        Path in = new Path("hdfs://192.168.1.101:9000/in/zhilian.csv");
        Path out = new Path("hdfs://192.168.1.101:9000/out/");

        FileSystem fileSystem = FileSystem.get(conf);
        fileSystem.delete(out, true);

        FileInputFormat.addInputPath(job, in);
        FileOutputFormat.setOutputPath(job, out);

        System.exit(job.waitForCompletion(true) ? 0 : 1);

    }
}

改进

1、在之前的代码中,key或value不需要输出值时用的是new Text(""),改进为提前new一个类型为Text值为空的静态变量Text nullData = new Text(""),要输出值为空的Text型数据时直接输出nullData,减少了new来开辟空间的次数就减少了内存的占用

2、因为在输出时要把String类型值转化为Text类型,用的方式也是new Text(data),也是不断new,优化方法创建一个静态Text类型变量Text text = new Text(""),输出data时text.set(data)直接把text输出

3、运行结束后会在我们设定的hdfs目录下生成路径和文件,但如果此路径或文件存在来,就会报出路径或文件已存在的异常,所以每一次运行前都要先递归删除这个路径,很麻烦,所以这次会先判断输出路径,如果这个路径或文件已存在就删了,更人性化了

 

注意:一定以注意编码问题,对文件进行清洗时一定要确保是UTF-8的编码,最好在爬虫保存数据时设定编码,不要保存为GBK编码,不然清洗出来的数据就成乱码了,hadoop中默认编码就是UTF-8的,如果数据量很大不好转码就只能在map函数获取数据前先转码,也就是把String line = value.toString();替换为String line = new String(value.getBytes(), 0, value.getLength(), "GBK");GBK为文件当前编码

此代码打jar包上传到集群然后在启动hadoop相关进程后hadoop jar + jar包名,还要注意导包一定要导对
 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值