首页 > 其他分享 >Day4—电商日志数据分析

Day4—电商日志数据分析

时间:2024-06-09 22:58:25浏览次数:14  
标签:null java url Day4 append 日志 电商 ETL

项目要求:

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

  • 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包

在这里插入图片描述
成功打成jar包

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

在这里插入图片描述
成功进行mapreduce操作

5.查看结果

在hdfs中查看结果
在这里插入图片描述
成功进行ETL操作

遇到的问题

  • 运行jar包时报错
  • 报错信息为:
Exception in thread "main" java.lang.UnsupportedClassVersionError: log1/LogAnalysisDriver has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at org.apache.hadoop.util.RunJar.run(RunJar.java:316)
	at org.apache.hadoop.util.RunJar.main(RunJar.java:236)

解决方法

  • 在项目的属性里设置jdk版本,方法是右击项目–>settings–>Build,Execution,Deployment–>Java compiler --> Project bytecode version -->设置为8

在这里插入图片描述

总结

在本实验中,通过ETL操作对电商日志文件进行了有效处理,实现了数据的高效管理和分析。ETL操作的必要性在于它允许我们只关注和处理那些对业务分析有价值的字段,而不是解析整个日志文件的所有数据。这不仅提高了数据处理的效率,还减少了存储和计算资源的消耗。通过这种方式,项目能够快速获得关于页面浏览量和用户地理位置分布的洞察,帮助电商企业优化用户体验和制定市场策略。。

标签:null,java,url,Day4,append,日志,电商,ETL
From: https://blog.csdn.net/weixin_61822557/article/details/139552668

相关文章

  • 11 深入理解Linux文件系统与日志分析
    目录11.1深入理解Linux文件系统    11.1.1inode与block详解        1.inode和block概述        2.inode的内容        3.inode的号码        4.inode的大小    11.1.2硬链接与......
  • SpringCloud-OpenFeign拓展-连接池、最佳使用方法、日志输出
    目录1OpenFeign连接池1.1常见连接类型1.2连接池使用方法1.2.1引入依赖1.2.2开启连接池功能1.2.3配置完成,重启实例即可,底层将更改设置。2OpenFeign最佳使用方法2.1每个微服务都是单独的project,内部有三个独立模块2.2每个微服务都是一个module,一个project,内设......
  • Day24.日志轮换
    1.setting.py文件中,LOGGING_DIC----->handlers下的default字典中的参数解释注:`maxBytes`和`backupCount`两个key值的使用#打印到文件的日志,收集info及以上的日志'default':{'level':'DEBUG',#'class':'lo......
  • nginx快速分析日志并找出攻击IP
    第一步:分析NGINX日志分析日志主要目的是寻找那些异常活跃的IP地址,通过以下命令可以快速找出。 cataccess.log|awk'{print$1}'|sort|uniq-c|sort-rn|head-10命令说明:cataccess.log:将access.log文件的内容输出到标准输出。awk'{print$1}':awk是一个强大的文本......
  • Day47 代码随想录打卡|二叉树篇---最大二叉树
    题目(leecodeT654):给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。返回 nu......
  • Nginx访问日志
         Nginx日志是NginxWeb服务器产生的记录文件,主要用于跟踪和分析服务器的访问情况以及错误信息。Nginx日志主要分为两大类:访问日志(access_log):访问日志记录了每一次客户端对Nginx服务器的HTTP请求的详细信息,这对于统计分析、流量监控、用户行为分析等非常有用......
  • C语言学习日志4-关键字iii
    1.6,if、else组合1.6.1,bool变量与“零值”进行比较boolbTestFlag=FALSE;C),if(bTestFlag);if(!bTestFlag);1.6.2,float变量与“零值”进行比较floatfTestVal=0.0;B),if((fTestVal>=-EPSINON)&&(fTestVal<=EPSINON));//EPSINON为定义好的精度。1.6.3,指......
  • C语言学习日志2-关键字i
    1.1,最宽恒大量的关键字----autoauto:它很宽恒大量的,你就当它不存在吧。编译器在默认的缺省情况下,所有变量都是auto的。1.2,最快的关键字----registerregister:这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。注意是尽可能,不是绝......
  • C语言学习日志1-定义与声明
    什么是定义:所谓的定义就是(编译器)创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名或对象名。一个变量或对象在一定的区域内(比如函数内,全局等)只能被定义一次,如果定义多次,编译器会提示你重复定义同一个变量或对象。什么是声明:有两重含......
  • 成为MySQL DBA后,再看ORACLE数据库(七、日志体系)
    说起数据库的日志,一般有redo日志、归档日志、错误日志、审计日志等,不同的数据库为了满足其特定的功能会有不同类型的日志。在ORACLE的日常运维中,可能接触得最多的就是redo日志、归档日志、告警日志、闪回日志这几种日志。在ORACLE知识体系中,一般把redo、undo、checkpoint这几个知......