基于华为开发者空间,用大数据带你挖掘电商Top10热门品类

B站影视 内地电影 2025-09-12 04:25 1

摘要:本案例的数据是采集电商网站的用户行为数据,主要包含用户的4种行为:搜索、点击、下单和支付。数据格式说明如下:(1)数据采用下划线分割字段;(2)每一行表示用户的一个行为,所以每一行只能是4种行为中的一种;(3)如果搜索关键字是null,表示这次不是搜索;(4)

1.1 背景介绍

随着电商行业的蓬勃发展,海量交易数据不断产生。了解哪些品类在市场中最受消费者青睐,成为商家优化库存、制定营销策略以及平台规划布局的关键依据。

1.2 适用对象

企业个人开发者高校学生(有一定代码基础)

1.3 案例时间

本案例总时长预计30分钟。

1.4 案例流程


说明:
① 用户登录云主机;
② 打开CodeArts IDE获取项目代码;
③ 进行环境准备,配置JDK17;
④ 启动项目的前后端代码,在浏览器中进行页面结果展示。

1.5 资源总览

资源名称规格单价(元)时长(h)JDKjdk17免费0.5开发者空间-华为云 - 云主机鲲鹏通用计算增强型 kc2 | 4vCPUs | 8G | Ubuntu免费0.5最新案例动态,请查阅《大数据带你挖掘电商Top10热门品类》「链接」。小伙伴快来领取华为开发者空间进行实操体验吧!2 操作步骤

2.1 数据格式简介

本案例的数据是采集电商网站的用户行为数据,主要包含用户的4种行为:搜索、点击、下单和支付。数据格式说明如下:
(1)数据采用下划线分割字段;
(2)每一行表示用户的一个行为,所以每一行只能是4种行为中的一种;
(3)如果搜索关键字是null,表示这次不是搜索;
(4)如果点击的品类id和产品id是-1表示这次不是点击;
(5)下单行为来说一次可以下单多个产品,所以品类id和产品id都是多个,id之间使用逗号分割。如果本次不是下单行为,则他们相关数据用null来表示;
(6)支付行为和下单行为类似。

2.2 需求分析

Top10热门品类,是指产品的分类。分别统计每个品类点击的次数,下单的次数和支付的次数。先按照点击数排名,靠前的就排名高;如果点击数相同,再比较下单数;下单数再相同,就比较支付数。
计算结果格式类似:

智能手机 ,点击品类书,下单品类数,支付品类数宠物玩具 ,点击品类书,下单品类数,支付品类数休闲食品,点击品类书,下单品类数,支付品类数

2.3 环境准备

2.3.1 获取项目代码

1.拉取前端代码

git clone https://gitcode.com/CaseDeveloper/E-Commerce-commerce-top10-Web.git

前端部署参考案例:在云主机上进行电商项目VUE前端部署
2.拉取后端代码

git clone https://gitcode.com/CaseDeveloper/E-Commerce-commerce-top10.git

后端部署参考案例:基于云主机的CodeArts IDE运行Java电商项目

2.3.2 编写代码

1.打开CodeArts IDE for Java


2.打开工程E-Commerce-commerce-top10


3.打开项目代码

在工程src下datas文件夹中user_visit_action.txt是需要用到的数据。在utils下Top10.java 是实现代码。
Top10.java代码如下:package org.example.utils;import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaRDD;import org.apache.spark.api.java.JavaSparkContext;import org.apache.spark.api.java.function.VoidFunction;import org.apache.spark.util.AccumulatorV2;import org.example.Entity.BusinessData;import org.example.Entity.CategoryCountInfo;import org.example.Entity.ProductIdToNameMapEnum;import org.example.Entity.UserVisitAction;import scala.Tuple2;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;//自定义AccumulatorV2实现类,用于累加计算品类相关的点击、下单、支付次数class CategoryCountAccumulator extends AccumulatorV2, Long>> implements Serializable{ private Map, Long> map1 = new HashMap; // 判断是否为初始状态(即map为空) @Override public boolean isZero { return map1.isEmpty; } // 复制累加器实例 @Override public AccumulatorV2, Long>> copy { CategoryCountAccumulator newACC = new CategoryCountAccumulator; newACC.map1 = new HashMap(this.map1); return newACC; } // 重置累加器,清空内部存储的map数据 @Override public void reset { map1.clear; } // 处理单个分区内的数据,根据不同的业务行为(点击、下单、支付)累加相应的次数 @Override public void add(UserVisitAction action) { // 点击行为 if (action.getClick_category_id!= -1) { Tuple2key = new Tuple2(action.getClick_category_id + "", "click"); map1.put(key, map1.getOrDefault(key, 0L) + 1L); } // 下单行为 else if (!"null".equals(action.getOrder_category_ids)) { String ids = action.getOrder_category_ids.split(","); for (String id : ids) { Tuple2key = new Tuple2(id, "order"); map1.put(key, map1.getOrDefault(key, 0L) + 1L); } } // 支付行为 else if (!"null".equals(action.getPay_category_ids)) { String ids = action.getPay_category_ids.split(","); for (String id : ids) { Tuple2key = new Tuple2(id, "pay"); map1.put(key, map1.getOrDefault(key, 0L) + 1L); } } } // 合并不同分区的累加结果 @Override public void merge(AccumulatorV2, Long> map2 = other.value; for (Map.Entry, Long> entry : map2.entrySet) { Tuple2k = entry.getKey; Long v = entry.getValue; map1.put(k, map1.getOrDefault(k, 0L) + v); } } // 获取累加器当前的值(即存储了各品类操作次数的map) @Override public Map, Long> value { return map1; } } public class Top10 implements Serializable { public static Listtop10 { SparkConf conf = new SparkConf.setAppName("Top10").setMaster("local[*]"); // 创建JavaSparkContext,该对象是提交的入口 JavaSparkContext sc = new JavaSparkContext(conf); Top10 top10 = new Top10; ListsparkRun = top10.sparkRun(sc); // 9. 关闭连接 sc.stop; return sparkRun; } public ListsparkRun(JavaSparkContext sc) { // public static void main(String args) { // 创建SparkConf // SparkConf conf = new SparkConf.setAppName("Top10").setMaster("local[*]"); // 创建JavaSparkContext,该对象是提交的入口 // JavaSparkContext sc = new JavaSparkContext(conf); // 后续代码部分,如数据读取、处理、累加器使用、排序取前10以及关闭连接等操作保持不变 // 1. 读取数据 JavaRDDdataRDD = sc.textFile("src/datas/user_visit_action.txt"); // 2. 将读到的数据进行切分,并且将切分的内容封装为UserVisitAction对象 JavaRDDactionRDD = dataRDD.map(line -> { String fields = line.split("_"); return new UserVisitAction( fields[0], Long.parseLong(fields[1]), fields[2], Long.parseLong(fields[3]), fields[4], fields[5], Long.parseLong(fields[6]), Long.parseLong(fields[7]), fields[8], fields[9], fields[10], fields[11], Long.parseLong(fields[12]) ); }); // 3. 创建累加器并注册 CategoryCountAccumulator acc = new CategoryCountAccumulator; sc.sc.register(acc, "myAcc"); // 4. 遍历actionRDD,使用累加器进行统计 actionRDD.foreach(new VoidFunction { @Override public void call(UserVisitAction action) { acc.add(action); } }); // 5. 获取累加器的值 Map, Long> accMap = acc.value; // 6. 对累加出来的数据按照类别进行分组 Map, Long>> groupMap = new HashMap; for (Map.Entry, Long> entry : accMap.entrySet) { Tuple2key = entry.getKey; String categoryId = key._1; if (!groupMap.containsKey(categoryId)) { groupMap.put(categoryId, new HashMap); } groupMap.get(categoryId).put(key, entry.getValue); } // 7. 对分组后的数据进行结构的转换为CategoryCountInfo对象 ListcategoryCountInfoList = new ArrayList; for (Map.Entry, Long>> entry : groupMap.entrySet) { String id = entry.getKey; Map, Long> map = entry.getValue; long clickCount = map.getOrDefault(new Tuple2(id, "click"), 0L); long orderCount = map.getOrDefault(new Tuple2(id, "order"), 0L); long payCount = map.getOrDefault(new Tuple2(id, "pay"), 0L); categoryCountInfoList.add(new CategoryCountInfo(id, clickCount, orderCount, payCount)); } // 8. 将转换后的数据进行排序(降序)取前10名 categoryCountInfoList.sort((left, right) -> { // 先按照点击次数降序比较 int clickCountCompare = Long.compare(right.getClickCount, left.getClickCount); if (clickCountCompare!= 0) { return clickCountCompare; } // 点击次数相同,按照订单次数降序比较 int orderCountCompare = Long.compare(right.getOrderCount, left.getOrderCount); if (orderCountCompare!= 0) { return orderCountCompare; } // 订单次数相同,按照支付次数降序比较 return Long.compare(right.getPayCount, left.getPayCount); }); MapproductIdToNameMap = ProductIdToNameMapEnum.INSTANCE.getProductIdToNameMap; Listtop10List = categoryCountInfoList.size > 10? categoryCountInfoList.subList(0, 10) : categoryCountInfoList; ListbusinessData = new ArrayList; for (CategoryCountInfo info : top10List) { String productName = productIdToNameMap.getOrDefault(info.getCategoryId, info.getCategoryId); BusinessData data = new BusinessData; data.setCategory(productName); data.setClickCount(info.getClickCount); data.setOrderCount(info.getOrderCount); data.setPaymentCount(info.getPayCount); businessData.add(data); // System.out.println("CategoryCountInfo(" + productName + ", " + info.getClickCount + ", " + info.getOrderCount + ", " + info.getPayCount + ")"); } // 9. 关闭连接 // sc.stop; return businessData; } } entity下,CategoryCountInfo,ProductIdToNameMapEnum,UserVisitAction是实体类。
代码如下:
a) CategoryCountInfo类:package com.example.entity;import java.io.Serializable;public class CategoryCountInfo implements Serializable {private String categoryId;private long clickCount;private long orderCount;private long payCount;public CategoryCountInfo(String categoryId, long clickCount, long orderCount, long payCount) {this.categoryId = categoryId;this.clickCount = clickCount;this.orderCount = orderCount;this.payCount = payCount;}public String getCategoryId {return categoryId;}public long getClickCount {return clickCount;}public void setClickCount(long clickCount) {this.clickCount = clickCount;}public long getOrderCount {return orderCount;}public void setOrderCount(long orderCount) {this.orderCount = orderCount;}public long getPayCount {return payCount;}public void setPayCount(long payCount) {this.payCount = payCount;}// 重写toString方法,按照期望的格式返回对象的字符串表示@Overridepublic String toString {return "CategoryCountInfo(" +categoryId + ',' ++ clickCount + ','++ orderCount + ','++ payCount +')';}}package com.example.entity;import java.util.HashMap;import java.util.Map;public enum ProductIdToNameMapEnum {INSTANCE;private final MapproductIdToNameMap; ProductIdToNameMapEnum { productIdToNameMap = new HashMap; productIdToNameMap.put("1", "智能手机"); productIdToNameMap.put("2", "护肤品套装"); productIdToNameMap.put("3", "运动鞋"); productIdToNameMap.put("4", "平板电脑"); productIdToNameMap.put("5", "休闲食品"); productIdToNameMap.put("6", "智能手环"); productIdToNameMap.put("7", "运动水杯"); productIdToNameMap.put("8", "儿童玩具"); productIdToNameMap.put("9", "营养补充剂"); productIdToNameMap.put("10", "家用小电器"); productIdToNameMap.put("11", "时尚外套"); productIdToNameMap.put("12", "蓝牙耳机"); productIdToNameMap.put("13", "创意家居饰品"); productIdToNameMap.put("14", "车载香水"); productIdToNameMap.put("15", "智能手表"); productIdToNameMap.put("16", "美妆工具"); productIdToNameMap.put("17", "电子游戏"); productIdToNameMap.put("18", "户外背包"); productIdToNameMap.put("19", "宠物玩具"); productIdToNameMap.put("20", "健身器材"); } public MapgetProductIdToNameMap { return productIdToNameMap; } }

c) UserVisitAction 类:

package com.example.entity;// 用户访问动作表对应的Java类public class UserVisitAction {private String date;private long user_id;private String session_id;private long page_id;private String action_time;private String search_keyword;private long click_category_id;private long click_product_id;private String order_category_ids;private String order_product_ids;private String pay_category_ids;private String pay_product_ids;private long city_id;public UserVisitAction(String date, long user_id, String session_id, long page_id, String action_time,String search_keyword, long click_category_id, long click_product_id,String order_category_ids, String order_product_ids, String pay_category_ids,String pay_product_ids, long city_id) {this.date = date;this.user_id = user_id;this.session_id = session_id;this.page_id = page_id;this.action_time = action_time;this.search_keyword = search_keyword;this.click_category_id = click_category_id;this.click_product_id = click_product_id;this.order_category_ids = order_category_ids;this.order_product_ids = order_product_ids;this.pay_category_ids = pay_category_ids;this.pay_product_ids = pay_product_ids;this.city_id = city_id;}public String getDate {return date;}public long getUser_id {return user_id;}public String getSession_id {return session_id;}public long getPage_id {return page_id;}public String getAction_time {return action_time;}public String getSearch_keyword {return search_keyword;}public long getClick_category_id {return click_category_id;}public long getClick_product_id {return click_product_id;}public String getOrder_category_ids {return order_category_ids;}public String getOrder_product_ids {return order_product_ids;}public String getPay_category_ids {return pay_category_ids;}public String getPay_product_ids {return pay_product_ids;}public long getCity_id {return city_id;}}

2.3.3 编辑配置

点击右上角编辑配置。


在VM options: 配置项,添加如下配置(jdk版本高于1.8需要添加)。

--add-opens java.base/sun.nio.ch=ALL-UNNAMED

2.4 运行代码

1.点击页面右上角的执行按钮运行后端代码。


2.在命令行运行前端代码
在前端代码目录执行命令:

npm run dev

运行成功后显示如下:


3.打开页面http://localhost:3000/products,访问电商项目页面。


注册账号并登录,然后点击页面的“top10”商品按钮。


可以看到Top10热门的商品品类展示如下。


至此,电商top10热门品类挖掘实操全部完成。

来源:爱就旅行

相关推荐