【大数据学习篇10】Spark项目实战~网站转化率统计

学习目标/Target

掌握网站转化率统计实现思路

了解如何生成用户浏览网页数据

掌握如何创建Spark连接并读取数据集

掌握利用Spark SQL统计每个页面访问次数

 掌握利用Spark SQL获取每个用户浏览网页的顺序

掌握利用Spark SQL合并同一用户浏览的网页

 掌握利用Spark SQL统计每个单跳的次数

掌握利用Spark SQL计算页面单跳转化率

掌握将数据持久化到HBase数据库

熟悉通过Spark On YARN运行程序

概述

        网站转化率(conversion rate)是指用户进行了相应目标行动的访问次数与总访问次数的比率。这里所指的相应目标行动可以是用户登录、用户注册、用户浏览、用户购买等一系列用户行为,因此网站转化率是一个广义的概念。页面单跳转化率是网站转化率的一种统计形式,通过统计页面单跳转化率,来优化页面布局及营销策略,使访问网站的用户可以更深层次的浏览网站。本章我们将对用户浏览网页数据进行分析,从而统计出页面单跳转化率。

1. 数据集分析

        通过编写的Java程序模拟生成用户浏览网页数据作为数据集,数据集中的每一行数据代表一个用户的浏览行为,所有浏览行为都与页面-和用户有关。

{ "actionTime":"2020-07-22 06:34:02", "sessionid":"98ac879b5a0a4a4eb117dffd84da1ff4", "pageid":3, "userid":8 }

actionTime: 用户访问页面的时间;

sessionid:用于标识用户行为的唯一值;

pageid:用户浏览网页的ID;

userid:用户ID;

2.实现思路分析

        当用户浏览网页时,通过当前浏览页面(A)跳转到另一个页面(B),此用户行为被称为一次A→B的单跳。如计算A→B的页面单跳转化率,则计算公式如下。

A→B页面单跳转化率=A→B的单跳总数/A总访问次数

计算页面单跳转化率需要两部分数据,分别是A→B的单跳总数和A总访问次数。

A总访问次数可以通过聚合操作获取,A→B的单跳总数实现思路如下。

根据用户ID和访问时间对数据集进行排序操作,获取每个用户浏览网页的顺序。

根据用户ID对排序后的数据进行分组操作,将同一用户浏览的网页进行合并。

对分组后的数据进行转换操作,将同一用户浏览的网页按照浏览顺序转换为单跳形式。

对转换后的数据进行聚合操作统计每个单跳的总数,其中包括A→B的单跳总数。

页面单跳转化率统计实现过程。

3.实现网站转化率统计

 3.1  生成用户浏览网页数据

        在项目SparkProject的 java目录新建Package包“cn.itcast.conversion”,用于存放实现网站转化率统计的Java文件。在包“cn.itcast.conversion”中创建文件GenerateData.java,用于模拟生成用户浏览网页数据。

        选中文件GenerateData.java并单击右键,在弹出的菜单栏选择“Run.GenerateData.main()”运行程序,生成用户浏览网页数据。

        程序运行完成后在“D:\\sparkdata”目录中会生成JSON文件user_conversion.json,该文件包含用户浏览网页数据。

3.2  修改pom.xml文件

        由于实现网站转化率统计是通过Spark SQL程序实现,所以需要在项目SparkProject的pom.xml文件中添加Spark SQL依赖。

<dependency>

     <groupId>org.apache.spark</groupId>

     <artifactId>spark-sql_2.11</artifactId>

     <version>2.3.2</version>

</dependency>

3.3  创建Spark连接并读取数据集

        在项目SparkProject的包“cn.itcast.conversion”中创建文件PageConversion.java,用于实现网站转化率统计。

public class PageConversion {

    public static void main(String[] arg){

    //实现Spark SQL程序

    }

        在文件PageConversion.java的main()方法中创建SparkSession对象,用于实现Spark SQL程序。

SparkSession spark = SparkSession

    .builder()

    //设置Application名称为page_conversion

    .appName("page_conversion")

    .getOrCreate();

        在文件PageConversion.java的main()方法中,调用SparkSession对象的read().json()方法读取外部JSON文件,将JSON文件中的数据加载到userConversionDS。

Dataset<Row> userConversionDS = spark.read().json(arg[0]);

        在文件PageConversion.java的main()方法中,调用DataSet的createOrReplaceTempView()方法,将userConversionDS创建为全局临时视图conversion_table。        

userConversionDS.createOrReplaceTempView("conversion_table");

3.4  统计每个页面访问次数

在文件PageConversion.java的main()方法中,调用SparkSession的sql()方法统计每个页面访问次数,将统计结果加载到pageIdPvDS。

Dataset<Row> pageIdPvDS = spark

    .sql("select pageid,count(*) as pageid_count " +

            "from conversion_table " +

            "group by pageid");

3.5  获取每个用户浏览网页的顺序\

        在文件PageConversion.java的main()方法中,调用SparkSession的sql()方法对每个用户浏览网页的顺序进行排序,将排序结果加载到useridGroupSortDS。

Dataset<Row> useridGroupSortDS = spark

    .sql("select userid,actionTime,pageid " +

            "from conversion_table " +

            "order by userid,actionTime");

        在文件PageConversion.java的main()方法中,调用DataSet的createOrReplaceTempView()方法,将useridGroupSortDS创建为全局临时视图conversion_group_sort_table。

useridGroupSortDS.createOrReplaceTempView("conversion_group_sort_table");

3.6  合并同一用户浏览的网页

        在文件PageConversion.java的main()方法中,调用SparkSession的sql()方法对同一用户浏览的网页进行合并,将合并结果加载到pageConversionRDD。为了后续使用flatMap()算子对合并后的数据进行扁平化处理,这里通过SparkSession的toJavaRDD()方法将DataSet转为JavaRDD。

JavaRDD<Row> pageConversionRDD = spark.sql("select userid," +     "concat_ws(',',collect_list(pageid)) as column2s " +     "from conversion_group_sort_table " +     "group by userid").toJavaRDD();

3.7  统计每个单跳的次数

        在文件PageConversion.java的main()方法中,使用flatMap()算子对pageConversionRDD进行扁平化处理,根据用户浏览网页的顺序将相邻网页拼接为单跳,将处理结果加载到rowRDD。

JavaRDD<Row> rowRDD = pageConversionRDD.flatMap(new FlatMapFunction<Row, Row>() {     @Override     public Iterator<Row> call(Row row) throws Exception {

        List<Row> list = new ArrayList<>();

        String[] page = row.get(1).toString().split(",");

        String pageConversionStr = "";  

      for (int i = 0;i<page.length-1;i++){

        if (!page[i].equals(page[i+1])){

            pageConversionStr = page[i]+"_"+page[i+1];

            list.add(RowFactory.create(pageConversionStr));

        }

    }

        return list.iterator();

    }

});

        在文件PageConversion.java的main()方法中,调用SparkSession的createDataFrame()方法和 registerTempTable()方法,将存储单跳数据的rowRDD注册临时表page_conversion_table。

StructType schema = DataTypes.createStructType(new StructField[]{     DataTypes.createStructField( "page_conversion",DataTypes.StringType,true)     }); spark.createDataFrame(rowRDD, schema).registerTempTable("page_conversion_table");

        在文件PageConversion.java的main()方法中,使用SparkSession的sql()方法统计每个单跳的次数,根据统计结果创建全局临时视图page_conversion_count_table。

spark.sql(

    "select page_conversion," +

    "count(*) as page_conversion_count " +

    "from page_conversion_table " +

    "group by page_conversion")

    .createOrReplaceTempView("page_conversion_count_table");

3.8  计算页面单跳转化率

        通过页面单跳转化率的计算公式得知,若要计算单跳A→B的页面单跳转化率,首先需要获取页面A的访问次数,然后需要获取单跳A→B的次数,最终将这两部分数据代入页面单跳转化率的计算公式中计算单跳A→B的页面单跳转化率。 在计算每个单跳的页面单跳转化率之前,需要将每个页面与每个单跳进行一一对应,也就是说如果计算单跳A→B的页面单跳转化率,那么代入页面单跳转化率计算公式中的一定是页面A的访问次数,而不能是页面B或C的访问次数。

        在文件PageConversion.java的main()方法中,使用SparkSession的sql()方法拆分单跳为起始页面和结束页面,将拆分后的数据加载到pageConversionCountDS。

Dataset<Row> pageConversionCountDS = spark

    .sql("select page_conversion_count," +

        "split(page_conversion,'_')[0] as start_page," +

        "split(page_conversion,'_')[1] as last_page " +

        "from page_conversion_count_table");

        在文件PageConversion.java的main()方法中,使用join()算子对pageIdPvDS(存储每个页面访问的次数)和pageConversionCountDS(存储每个单跳拆分后的数据)进行连接,根据连接结果创建全局临时视图page_conversion_join。

pageConversionCountDS.join(

            pageIdPvDS,

            new Column("start_page").equalTo(new Column("pageid")),             "left").createOrReplaceTempView("page_conversion_join");

        在文件PageConversion.java的main()方法中,使用SparkSession的sql()计算页面单跳转化率,将计算结果加载到resultDS。

Dataset<Row> resultDS = spark .sql("select " +

    "concat(pageid,'_',last_page) as conversion," +

    "round(" +

    "CAST(page_conversion_count AS DOUBLE)/CAST(pageid_count AS DOUBLE)" +

    ",3) as rage " +

   "from page_conversion_join");

3.9  数据持久化

        在PageConversion类中添加方法conversionToHBase(),用于将页面单跳转化率统计结果持久化到HBase数据库中,该方法包含参数dataset,表示需要向方法中传递页面单跳转化率统计结果数据。

public static void conversionToHBase(Dataset<Row> dataset) throws IOException {     HbaseUtils.createTable("conversion","page_conversion");

    String[] column = {"convert_page","convert_rage"};

    dataset.foreach(new ForeachFunction<Row>() {

        @Override

        public void call(Row row) throws Exception {

            String conversion = row.get(0).toString();

            String rage = row.get(1).toString();

            String[] value ={conversion,rage};

            HbaseUtils.putsToHBase("conversion",conversion+rage,"page_conversion",column,value);

        }

    });

}

        在文件PageConversion.java的main()方法中,调用conversionToHBase()方法并传入参数resultDS,用于在Spark SQL程序中实现conversionToHBase()方法,将页面单跳转化率统计结果数据持久化到HBase数据库中的数据表conversion。

try {

      conversionToHBase(resultDS);

} catch (IOException e) {  

    e.printStackTrace(); }

HbaseConnect.closeConnection();

spark.close();

4.运行程序

        在IntelliJ IDEA中将页面单跳转化率统计程序封装成jar包,并上传到集群环境中,通过spark-submit将程序提交到YARN中运行。

封装jar包:

由于在封装各区域热门商品Top3分析程序jar包时,将程序主类指向了“cn.itcast.top3.AreaProductTop3”,因此这里需要将pom.xml文件中的程序主类修改为“cn.itcast.conversion.PageConversion”。根据封装热门品类Top10分析程序jar包的方式封装页面单跳转化率统计程序。将封装完成的jar包重命名为“PageConversion”,通过远程连接工具SecureCRT将PageConversion.jar上传到虚拟机Spark01的/export/SparkJar/目录下。

将数据集上传到本地文件系统:

        使用远程连接工具SecureCRT连接虚拟机Spark01,在存放数据文件的目录/export/data/SparkData/(该目录需提前创建)下执行“rz”命令,将数据集user_conversion.json上传至本地文件系统。

在HDFS创建存放数据集的目录:

将数据集上传到HDFS前,需要在HDFS的根目录创建目录page_conversion,用于存放数据集user_conversion.json。

hdfs dfs -mkdir /page_conversion

上传数据集到HDFS:

将目录/export/data/SparkData/下的数据集user_conversion.json上传到HDFS的page_conversion目录下,具体命令如下。

hdfs dfs -put /export/data/SparkData/user_conversion.json /page_conversion

提交页面单跳转化率统计程序到YARN集群:

        通过Spark安装目录中bin目录下的shell脚本文件spark-submit提交页面单跳转化率统计程序到YARN集群运行。

spark-submit \

--master yarn \

--deploy-mode cluster \

--num-executors 3 \

--executor-memory 2G \

--class cn.itcast.conversion.PageConversion \

/export/SparkJar/PageConversion.jar /page_conversion/user_conversion.json

查看程序运行结果:

在虚拟机Spark01执行“hbase shell”命令,进入HBase命令行工具。

在HBase命令行工具中执行“list”命令,查看HBase数据库中的所有数据表。

> list

TABLE                                                                                                                                       conversion 

查看程序运行结果

在HBase命令行工具执行“scan 'conversion'”命令,查看数据表conversion中所有数据。

        本文主要讲解了如何通过用户浏览网页数据实现网站转化率统计,首先我们对数据集进行分析,使读者了解用户浏览网页数据的数据结构。接着通过实现思路分析,使读者了解网站转化率统计的实现流程。然后通过IntelliJ IDEA开发工具实现网站转化率统计程序并将统计结果存储到HBase数据库,使读者掌握运用Java语言编写Spark SQL和HBase程序的能力。最后封装网站转化率统计程序并提交到集群运行,使读者掌握运用IntelliJ IDEA开发工具封装Spark SQL程序以及Spark ON YARN模式运行Spark SQL程序的方法。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/23369.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

qt quick(qml)通过arcgis导入自定义格式地图(Windows 版本)

参考ArcGIS Maps SDK for Qt 参考Display a map 安装 预先安装的软件 安装ArcGIS SDK 点击ArcGIS Maps SDK for Qt 注册账号 要注册成developer版本用户的&#xff0c;不然之后可能没办法生成API 下载 下载之后安装&#xff0c;一路next就可以了 在QT中创建ArcGIS项目…

安科瑞对于热继电器对电动机保护的探讨

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要:电动机烧毁是每一个生产企业都无法回避的现象&#xff0c;怎样加强电动机保护&#xff0c;使生产工艺系统的稳定&#xff0c;减少企业非正常停机时间。电动机保护成为电气技术人员一个重要课题。因此&#xff0c…

【数据结构】如何应用堆解决海量数据的问题

堆(Heap数据结构堆在计算机科学中有着广泛的应用&#xff0c;今天来介绍两种堆的应用&#xff1a;堆排序、Top-k问题&#x1f349; 堆排序 ​ 堆排序是一种基于堆数据结构的排序算法。它的基本思想是&#xff0c;将待排序的序列构建成一个大根堆&#xff08;或小根堆&#xff…

Keil 5 MDK 发律师函警告了,如何用STCubeIDE开发标准库的程序(STM32F103C8T6为例)

用STCubeIDE进行标准库开发 1、CubeIDE介绍 https://www.stmcu.com.cn/ecosystem/Cube/STM32CubeIDE 2、CubeIDE下载 点击上面的链接&#xff0c;登录即可下载 3、搭建Demo工程 新建一个工作空间 创建一个工程 选择芯片-STM32F103C8T6 填写工程信息 添加标准库到工程 标…

SSRS rdlc报表 六 报表分组和总计

报表分组和总计在报表中是一个很常用的功能&#xff0c;比如我们需要按部门进行分组&#xff0c;统计每个部门的费用支出&#xff0c;或者在进一步分组&#xff0c;每个部门每个月的费用支出&#xff0c;通过rdlc报表&#xff0c;很容易实现这个需求。 我们下面要讲解的案例&a…

mac免费杀毒软件哪个好用?如何清理mac系统需要垃圾

CleanMyMac x是一款功能强大的Mac系统优化清理工具&#xff0c;使用旨在帮助用户更加方便的清理您系统中的所有垃圾&#xff0c;从而加快电脑运行速度&#xff0c;保持最佳性能&#xff0c;更加稳定、流畅、快速&#xff01;&#xff01;&#xff01; CleanMyMac X无疑是目前m…

开放式耳机和封闭式耳机的区别有哪些?开放式耳机有哪些推荐?

开放式耳机和封闭式耳机的区别主要在以下几个方面&#xff1a; 设计结构&#xff1a;开放式耳机通常有一个开放的设计&#xff0c;不需要塞入耳即可收听音乐&#xff0c;同时与外部环境进行交互。封闭式耳机则是封闭的设计&#xff0c;耳机驱动单元之间是封闭和隔离的&#xf…

使用IIS创建WEB服务

文章目录 前言一、Web服务是什么&#xff1f;1.Web服务概述2.如何获取网页资源3.常见Web服务端软件4.什么是IIS 二、安装IIS1.安装Web服务器角色2.准备网页文件3.配置Web站点4.客户端浏览例&#xff1a;配置IIS站点 三、虚拟主机概述1.虚拟Web主机2.虚拟主机的几种类型3.基于端…

国内做校园信息化的龙头企业公司有哪些?

随着数字化转型的加速&#xff0c;越来越多的学校开始寻求校园信息化的解决方案&#xff0c;相比于传统信息化模式&#xff0c;国内有哪些做校园信息化做得比较好的企业&#xff1f;他们采用的又是什么样的方式&#xff1f; 一文带你了解&#xff0c;零代码平台搭建校园信息化…

EMC模式如何助力新能源服务商攻坚克难

01. 什么是合同能源管理&#xff1f; 合同能源管理(EMC-Energy Management Contract)是一种新型的市场化节能机制,其实质就是以减少的能源费用来支付节能项目全部成本的节能投资方式。&#xff1a;节能服务公司与用能单位以契约形式约定节能项目的节能目标&#xff0c;节能服务…

算法设计与分析期末总结

0000前言&#xff1a;基本是为了我自己看的一些我容易忘记的东西&#xff0c;为考试作准备把&#xff0c;主要使后半部分的知识&#xff0c;前半部分请看算法设计与分析阶段考总结 第五章 回溯算法是一种系统地搜索问题的解的方法。某个问题的所有可能解的称为问题的解空间&…

华为OD机试真题 Java 实现【寻找相似单词】【2023Q2 200分】

一、题目描述 给定一个可存储若干单词的字典&#xff0c;找出指定单词的所有相似单词&#xff0c;并且按照单词名称从小到大排序输出。 单词仅包括字母&#xff0c;但可能大小写并存&#xff08;大写不一定只出现在首字母&#xff09;。 相似单词说明&#xff1a; 给定一个…

北京君正应用案例:双镜头双画面乔安枪球联动摄像头

你是否遇到过这种问题&#xff1f; 既要看店铺又要看柜台 既要看车又要看大门 雷龙发展提供原厂技术支持&#xff0c;并提供君正集成电路完整解决方案&#xff0c;大大降低你的开发难度及开发时间。 单镜头摄像头一台不够广 出现监控盲区&#xff0c;让小偷有可趁之机 只能装两…

linuxOPS基础_Linux文件管理

Linux下文件命名规则 可以使用哪些字符&#xff1f; 理论上除了字符“/”之外&#xff0c;所有的字符都可以使用&#xff0c;但是要注意&#xff0c;在目录名或文件名中&#xff0c;不建议使用某些特殊字符&#xff0c;例如&#xff0c; <、>、&#xff1f;、* 等&…

Nacos、Eureka和Zookeeper有什么区别

Nacos、Eureka和Zookeeper都是服务注册中心&#xff0c;它们的主要功能是管理分布式系统中各个微服务实例的注册与发现。它们之间的主要区别在于&#xff1a; 1. 语言支持&#xff1a;Nacos是用Java语言开发的&#xff0c;Eureka是用Java语言开发的&#xff0c;Zookeeper则是用…

开源项目ChatGPT-website再次更新,累计下载使用1600+

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

【数组的深刻理解】

#include<stdio.h> #define N 10 int main() {int a[N] { 0 }; //定义并初始化数组return 0; } 概念&#xff1a;数组是具有相同数据类型的集合。 数组的内存布局 #include<stdio.h> int main() {int a 10;int b 20;int c 30;printf("%p\n", &a…

一文带你了解MySQL之optimizer trace神器的功效

前言&#xff1a; 对于MySQL 5.6以及之前的版本来说&#xff0c;查询优化器就像是一个黑盒子一样&#xff0c;你只能通过EXPLAIN语句查看到最后优化器决定使用的执行计划&#xff0c;却无法知道它为什么做这个决策。这对于一部分喜欢刨根问底的小伙伴来说简直是灾难&#xff1…

基于ARIMA-LSTM组合模型的预测方法研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

招投标系统简介 招投标系统源码 java招投标系统 招投标系统功能设计

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…