Day3—电商日志数据分析
项目要求:
根据电商日志文件,分析:
- 1 . 统计页面浏览量(每行记录就是一次浏览)
- 2 . 统计各个省份的浏览量 (需要解析IP)
- 3 . 日志的ETL操作(ETL:数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程)
为什么要ETL:没有必要解析出所有数据,只需要解析出有价值的字段即可。本项目中需要解析出:ip、url、pageId(topicId对应的页面Id)、country、province、city
前言
- Day3主要完成第二问 :
- 统计各个省份的浏览量 (需要解析IP)
二、实现步骤
1.导入数据
导入数据到指定目录下:
2.编写代码
Map阶段代码如下
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// Split the input line into fields based on the delimiter
String[] fields = value.toString().split("\u0001");
if (fields.length > 13) {
// Assuming the IP address is in the 14th field (index 13)
String ip = fields[13];
String log = value.toString();
LogParser parser = new LogParser();
Map<String, String> logInfo = parser.parse(log);
if (StringUtils.isNotBlank(logInfo.get("ip"))) {
IPParser.RegionInfo regionInfo = IPParser.getInstance().analyseIp(logInfo.get("ip"));
String province = regionInfo.getProvince();
if (StringUtils.isNotBlank(province)) {
context.write(new Text(province), new IntWritable(1));
} else {
context.write(new Text("-"), new IntWritable(1));
}
} else {
context.write(new Text("+"), new IntWritable(1));
}
}
}
这段Java代码是MapReduce框架中Mapper类的map方法的一个实现,它用于处理日志文件。以下是对这段代码的详细解释:
-
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {:这是map方法的声明,它重写了Mapper类中的map方法。
-
String[] fields = value.toString().split(“\u0001”);:将输入的Text对象value转换为字符串,并使用特定的分隔符(这里是\u0001,即ASCII码中的开始信息字符)来分割字符串,得到一个字段数组。
-
if (fields.length > 13) {:检查分割后的字段数组长度是否大于13,确保第14个字段(索引为13)存在。
-
String ip = fields[13];:从字段数组中获取第14个字段,假设这是IP地址字段,并将其存储在字符串变量ip中。
-
String log = value.toString();:将value转换为字符串,存储在变量log中,用于后续处理。
-
LogParser parser = new LogParser();:创建LogParser类的实例,这个类可能是用于解析日志的自定义类。
-
Map<String, String> logInfo = parser.parse(log);:调用LogParser实例的parse方法来解析日志字符串,得到一个包含日志信息的键值对映射。
-
if (StringUtils.isNotBlank(logInfo.get(“ip”))) {:使用StringUtils的isNotBlank方法检查解析出的IP地址是否不为空且不是空白字符串。
-
IPParser.RegionInfo regionInfo = IPParser.getInstance().analyseIp(logInfo.get(“ip”));:如果IP地址有效,使用IPParser的getInstance方法获取单例实例,并调用analyseIp方法来分析IP地址,获取地区信息。
-
String province = regionInfo.getProvince();:从地区信息对象中获取省份名称。
-
if (StringUtils.isNotBlank(province)) {:检查获取的省份名称是否不为空且不是空白字符串。
-
context.write(new Text(province), new IntWritable(1));:如果省份名称有效,使用context的write方法输出省份名称作为键和数值1作为值。
-
else { context.write(new Text(“-”), new IntWritable(1)); }:如果省份名称无效或为空,输出一个特殊标记"-"作为键和数值1作为值。
-
else { context.write(new Text(“+”), new IntWritable(1)); }:如果解析出的IP地址无效或为空,输出特殊标记"+"作为键和数值1作为值。
这段代码的主要目的是从日志文件中提取IP地址,并分析其所在的省份。如果成功提取并分析出省份,就将省份名称作为键输出;如果省份名称无效,则输出一个特殊标记;如果IP地址无效,则输出另一个特殊标记。这样,Reducer阶段就可以根据这些键来聚合数据,例如统计每个省份的日志条目数量或标记无效的日志条目。
Reduce阶段代码如下:
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
reduce方法接收三个参数:
- Text key:当前处理的键,通常是Mapper输出的键。
- Iterable values:与该键相关联的所有值的集合。
- Context context:Reducer的上下文对象,用于写入最终的输出结果。
3.打jar包进行上传
对编号的程序进行打jar包操作,并上传结果至hdfs,查看最终结果如下
总结
以上就是今天主要做的内容,编写了mapreduce代码来统计统计各个省份的浏览量 (需要解析IP)。最终得到了结果,培养的自己的动手能力和团队协作能力。希望在今后的学习生活中,将理论与实践充分结合,不断解决问题来提高自己。