招聘网站—MapReduce数据清洗
任务描述
利用MapReduce数据清洗
本关我们主要对爬取到的招聘数据进行清洗,清洗规则如下:
-
判断数据长度是否为 9 并判断数据字段是否完整,如有不完整字段(字段值为空),则清洗掉这一行数据;
-
对整条数据都一样的进行去重处理;
-
对数据字段中的城市(city)进行处理,只保留其中的市,舍弃区县,例如:深圳·南山区 -> 深圳;
-
对数据字段中的薪资(salary)计算处理,计算规则如下:
(1)mk-nk:(m+n)/2,结果保留两位小数(注意:也有可能出现 mK-nK)。 (2)如果薪资为其他格式的信息,清洗掉这一行数据。
-
将职位名称(job_name)、技能(skill)中的字母统一转换为小写字母;并将技能(skill)内容中的
·
使用|
代替。
- 清洗完的数据集存储到 /root/files 目录下,分隔方式为 \t。
数据集介绍
本数据集是招聘职位数据,包含九个字段的信息,数据集的字段含义说明如下:
字段名 | 说明 |
---|---|
job_name | 工作名称 |
city | 城市 |
salary | 薪水 |
workingExp | 工作年限 |
edu | 学历要求 |
company_name | 公司名称 |
company_size | 公司规模 |
welfare | 福利待遇 |
skill | 技能 |
部分数据展示
大数据实施管理专家 北京·海淀区 40k-60k 本科 建信金科 2000人以上 新团队,有发展前景 大数据 数据分析工程师 上海·张江 20k-35k 经验3-5年 本科 上海敬游软件 150-500人 年终奖金、五险一金、餐费补贴、弹性工作 游戏·数据分析 大数据开发工程师 成都·高新区 7k-14k 经验1-3年 本科 中电万维 500-2000人 公司稳定 福利好 13薪 定期体检 DB2·DBA·MySQL
清洗后数据展示:
数据分析工程师 上海 27.50 经验3-5年 本科 上海敬游软件 150-500人 年终奖金、五险一金、餐费补贴、弹性工作 游戏·数据分析 大数据开发工程师 成都 10.50 经验1-3年 本科 中电万维 500-2000人 公司稳定 福利好 13薪 定期体检 DB2·DBA·MySQL
编程要求
-
在右侧代码文件中的 Begin-End 区间编写代码,按照本关任务中的要求清洗数据,数据集存放在
/data/workspace/myshixun/clean/data/advertise.txt
中; -
清洗完的数据集存储到 /root/files 目录下。
测试说明
平台会对你编写的代码进行测试,若与预期输出一致,则算通关。
开始你的任务吧,祝你成功!
RecruitMap
package recruit.mapreduce; 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 java.io.IOException; public class RecruitMap extends Mapper<LongWritable, Text,Text,NullWritable> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { /********** Begin **********/ String[] fields =value.toString().split("\t"); boolean flag=true; if (fields.length==9) { int i=0; for (String field : fields) { if ("".equals(field) || field.trim() == null) { flag = false; break; } } if (flag) { if (fields[2].contains("k")){ fields[2]=fields[2].replace("k",""); }else if (fields[2].contains("K")){ fields[2]=fields[2].replace("K",""); } String re = "[0-9]+-[0-9]+"; flag = fields[2].matches(re); } if (flag) { fields[0]=fields[0].toLowerCase(); fields[8]=fields[8].toLowerCase(); fields[8]=fields[8].replaceAll("·","|"); fields[1] = fields[1].trim().split("·")[0].trim(); String maxsalary=fields[2].split("-")[0].trim(); String minsalary=fields[2].split("-")[1].trim(); Double avgsalary = (Double.parseDouble(maxsalary) + Double.parseDouble(minsalary)) / 2; fields[2] = String.format("%.2f", avgsalary); String result = ""; int len = 0; for (String field : fields) { len = len + 1; if (len == fields.length) { result = result + field; } else { result = result + field + "\t"; } } context.write(new Text(result), NullWritable.get()); } } /********** End **********/ } }
RecruitReduce
package recruit.mapreduce; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class RecruitReduce extends Reducer<Text,NullWritable,NullWritable,Text> { @Override protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException { /********** Begin **********/ context.write(NullWritable.get(),new Text(key)); /********** End **********/ } }
RecruitJob
package recruit.mapreduce; 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.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class RecruitJob { public static void main(String[] args) throws Exception { /********** Begin **********/ Configuration conf = new Configuration(); Job job = Job.getInstance(conf); job.setJarByClass(RecruitJob.class); job.setMapperClass(RecruitMap.class); job.setReducerClass(RecruitReduce.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(NullWritable.class); job.setOutputKeyClass(NullWritable.class); job.setOutputValueClass(Text.class); String outputpath = "/root/files"; Path path= new Path(outputpath); FileSystem fileSystem =path.getFileSystem(conf); if (fileSystem.exists(path)){ fileSystem.delete(path,true); } FileInputFormat.addInputPath(job, new Path("/data/workspace/myshixun/clean/data/advertise.txt")); FileOutputFormat.setOutputPath(job,path); job.waitForCompletion(true); /********** End **********/ } }