电商日志数据分析

一、项目要求:

根据电商日志文件,分析:

  1. 统计页面浏览量(每行记录就是一次浏览)
  2. 统计各个省份的浏览量 (需要解析IP)
  3. 日志的ETL操作(ETL:数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程)
    为什么要ETL:没有必要解析出所有数据,只需要解析出有价值的字段即可。本项目中需要解析出:ip、url、pageId(topicId对应的页面Id)、country、province、city

前言

Day4 主要完成第三问 :
日志的ETL操作(ETL:数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程)

二、使用步骤

1.分析题目

日志的ETL操作
ETL操作是指从原始数据中提取有用信息、转换数据格式并加载到目标系统的过程。在本项目中,需要提取日志中的IP、URL、pageId(topicId对应的页面Id)、country、province、city字段。

ETL步骤:

  • Extract(提取):从原始日志文件中提取出上述字段。
    Transform(转换):将提取的数据转换成适合分析的格式,例如,将IP地址转换为地理位置信息(国家、省份、城市)。
    Load(加载):将转换后的数据加载到目标数据库或数据仓库中,以便进一步分析。 ETL实现:
    Map阶段:设计一个Mapper来执行ETL操作,输出键值对,其中键可以是日志的唯一标识(如日志行号或时间戳),值是一个包含所有提取字段的对象或结构。
    Reduce阶段:在某些情况下,Reduce阶段可以用来进一步清洗或聚合ETL过程中的数据。
2.编写代码
private static final IntWritable one:用于计数的静态变量。
private Text outputKey:用于存储输出键的Text变量。
private LogParser logParser:日志解析器实例,用于解析日志数据。
private Logger logger:用于记录日志的SLF4J Logger实例。

Map阶段:

protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // 解析日志记录
        Map<String, String> logInfo = logParser.parse(value.toString());

        if (logInfo == null) {
            logger.error("日志记录的格式不正确或解析失败:" + value.toString());
            return;
        }

        // 获取需要的字段
        String ip = logInfo.get("ip");
        String url = logInfo.get("url");
        String country = logInfo.get("country");
        String province = logInfo.get("province");
        String city = logInfo.get("city");

        // 调用 GetPageId 获取 topicId
        String topicId = GetPageId.getPageId(url);
        logInfo.put("pageId", topicId);

        // 检查所有字段是否全部为空
        if (ip != null || url != null || topicId != null || country != null || province != null || city != null) {
            StringBuilder sb = new StringBuilder();

            if (ip != null && !ip.isEmpty()) sb.append("IP: ").append(ip).append(", ");
            if (url != null && !url.isEmpty()) sb.append("URL: ").append(url).append(", ");
            if (topicId != null && !topicId.isEmpty()) sb.append("PageId: ").append(topicId).append(", ");
            if (country != null && !country.isEmpty()) sb.append("Country: ").append(country).append(", ");
            if (province != null && !province.isEmpty()) sb.append("Province: ").append(province).append(", ");
            if (city != null && !city.isEmpty()) sb.append("City: ").append(city);

            // 移除末尾的逗号和空格
            String outputString = sb.toString().replaceAll(", $", "");
            outputKey.set(outputString);
            context.write(outputKey, one);
        } else {
            logger.error("所有字段为空,日志记录:" + value.toString());
        }
    }
}

Map<String, String> logInfo = logParser.parse(value.toString());:解析日志字符串,获取日志信息。

如果解析失败,使用logger记录错误,并返回。

从解析后的日志信息中提取ip、url、country、province和city字段。

String topicId = GetPageId.getPageId(url);:调用GetPageId.getPageId方法从URL中提取页面ID。

如果任何字段非空,构建输出字符串并写入Context。

如果所有字段都为空,记录错误日志。

使用StringBuilder构建包含所有非空字段的输出字符串。

context.write(outputKey, one);:将构建的输出键和计数写入Context。

Reduce阶段:

public class LogETLReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

    private IntWritable result = new IntWritable();

    @Override
    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);
    }

@Override protected void reduce(Text key, Iterable values, Context context):重写 reduce 方法,这是 Reducer 阶段的核心方法。
累加逻辑:

int sum = 0;:初始化一个整型变量 sum,用于累计所有输入值。

for (IntWritable val : values) { sum += val.get(); }:使用增强型 for 循环遍历与当前键 key 相关联的所有 IntWritable 对象,并累加它们的值。
设置结果:

result.set(sum);:将累计的总和赋值给 result 对象。
输出结果:

context.write(key, result);:使用 Context 对象的 write 方法将最终的键值对写入输出。键是输入的键(key),值是累计后的结果(result)。

这个类的目的是接收 Mapper 阶段输出的具有相同键的所有值,计算这些值的总和,并将结果输出。例如,在统计页面浏览量的场景中,如果 Mapper 输出了每个页面的浏览次数,Reducer 将接收相同页面标识的所有浏览次数,累加它们,并输出每个页面的总浏览量。

在ETL操作中,Reducer 可以用于聚合数据、清洗数据或转换数据格式,以便为最终的加载(Load)阶段准备数据。在这个例子中,Reducer 执行了聚合操作,将分散的数据点合并成有用的统计信息。

3.打jar包

请添加图片描述

4.将jar包传入hadoop目录下并运行

请添加图片描述

5.查看结果请添加图片描述
  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值