spark日志分析(一)—— 美团日志

本文详细介绍了如何使用Spark处理美团外卖平台的日志数据,包括数据加载、统计分析和HBase、Hive操作,同时展示了如何解析答题系统日志,包括数据预处理、字段提取和HBase、Hive表的创建与查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、数据描述

meituan_waimai_meishi.csv 是美团外卖平台的部分外卖 SPU(Standard Product Unit)
标准产品单元数据, 包含了外卖平台某地区一时间的外卖信息 。具体字段说明如下:

字段名称 中文名称 数据类型
spu_id 商品spuID String
shop_id 店铺ID String
shop_name 店铺名称 String
category_name 类别名称 String
spu_name SPU名称 String
spu_price SPU商品售价 Double
spu_originprice SPU商品原价 Double
month_sales 月销售量 Int
praise_num 点赞数 Int
spu_unit SPU单位 String
spu_desc SPU描述 String
spu_image 商品图片 String

二、数据下载

链接:meituan_waimai_meishi.csv
提取码:47k1

三、需求


1. 数据准备

请在HDFS中创建目录 /app/data/exam,并将meituan_waimai_meishi.csv 文件传到该目录,并通过HDFS命令查询出文档有多少行数据


  • 创建目录:
hdfs dfs -mkdir -p /app/data/exam
  • 上传文件:
hdfs dfs -put meituan_waimai_meishi.csv /app/data/exam/
  • 读取文件行数:
hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l

2. 使用 Spark 加载HDFS文件系统 meituan_waimai_meishi.csv 文件,并分别使用 RDD 和 SparkSQL 完成以下分析(不用考虑数据去重)

①统计每个店铺分别有多少商品(SPU)

②统计每个店铺的总销售额

③统计每个店铺销售额最高的前三个商品输出内容包括店铺名,商品名和销售额其中销售额为0的商品不进行统计计算,例如:如果某个店铺销售为0则不进行统计


2.1 使用RDD查询

  • 装载数据:
val fileRDD = sc.textFile("hdfs://hadoop-single:9000/app/data/exam/meituan_waimai_meishi.csv")
  • 过滤首行,以及错误数据(行数字段<12)
val spuRDD = fileRDD.filter(x => x.startsWith("spu_id")==false).map(x => x.split(",",-1)).filter(_.length==12)
  • ①统计每个店铺分别有多少商品(SPU)
spuRDD.map(x => (x(2),1)).reduceByKey(_+_).foreach(println)

在这里插入图片描述

  • ②统计每个店铺的总销售额

简单的写法:

spuRDD.map(x => (x(2),x(5).toDouble * x(7).toInt)).reduceByKey(_+_).foreach(println)

在这里插入图片描述

安全的写法,防止有格式不对的值无法转型 double 或者 int 会报错:

需先引入scala工具包:

import scala.util._

使用 Try() 包裹转换类型,转成Option对象 toOption,在使用 getOrElse()

spuRDD.map(x => (x(2),Try(x(5).toDouble).toOption.getOrElse(0.0) * Try(x(7).toInt).toOption.getOrElse(0))).reduceByKey(_+_).foreach(println)
  • ③统计每个店铺销售额最高的前三个商品输出内容包括店铺名,商品名和销售额其中销售额为0的商品不进行统计计算,例如:如果某个店铺销售为0则不进行统计
    思路: 用元祖形式统计三个字段:“店铺名shop_name x(2)”, “商品名spu_name x(4)”, “销售额spu_price * month_sales即x(5) * x(7)” -> 过滤销量为0的 -> 分组groupBy(shop_name) -> 自定义map中的内容map((shop_name,销售前三的销售额))

步骤1: 查询每个店铺每种商品的销售额

spuRDD.map(x => (x(2),x(4),Try(x(5).toDouble).toOption.getOrElse(0.0) * Try(x(7).toInt).toOption.getOrElse(0))).foreach(println)

部分截图如下:
在这里插入图片描述

步骤2: 过滤销量为0的商品,并进行分组

spuRDD.map(x => (x(2),x(4),Try(x(5).toDouble).toOption.getOrElse(0.0) * Try(x(7).toInt).toOption.getOrElse(0))).filter(_._3>0).groupBy(_._1).foreach(println)

部分截图如下:
在这里插入图片描述

注: 此时经过groupBy之后的,元组的格式变成了 (String, Iterable[(String, String, Double)])_.1表示商家名称,_.2是一个可迭代的对象,其中的元组 (String, String, Double) 代表原先map查找的字段 (店铺名称,商品名称,销售额)

如下如查询所示,分组后的元组格式为二元组,二元组中的第二个元素又是嵌套了很多个三元组
格式为: (shop_name, ( (shop_name,spu_name,spu_pricemonth_sales),(shop_name,spu_name,spu_pricemonth_sales) … )
在这里插入图片描述

步骤3: 完整答案,过滤销量为0的,取销量前三名,倒序输出sortBy(-1* )

//answer 1:
spuRDD.map(x => (x(2),x(4),Try(x(5).toDouble).toOption.getOrElse(0.0) * Try(x(7).toInt).toOption.getOrElse(0))).filter(_._3>0).groupBy(_._1).map(x => {
    
val shop_name = x._1;
val spu_name_totalPrice = x._2.toList.sortBy(-1*_._3).take(3).map(item => {
   item._2+"--"+item._3});
(shop_name,spu_name_totalPrice)
}).foreach(println)

在这里插入图片描述

返回结果元组格式:(string,List( (string,string), (string,string), (string,string) )

如下例查询结果所示:

(
三顾冒菜(曼城国际店),
List(单人荤素+1个米饭
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值