做什么?
我们需要去分析每一次的页面访问流程,也就是用户从进入网站到离开网站这个流程中所访问的页面顺序,也就是一个session中的页面访问顺序。
假如一个session的页面访问顺序为1,2,3,4,5,那么他访问的页面切片就是1_2,2_3,3_4,4_5,如果得到所有session的切面切片m_n,就可以计算每一种页面切片的个数,即count(m_n),就可以计算每一个页面单跳转化率。
需求解析
这个需求不是很难,只需要统计一下两个页面间的跳转数量除于总的跳转数即可.问题的关键在于如何转化数据,如下:
接着用countByKey就能统计出结果,完整代码如下:
完整代码:
其中需要注意的是,再spark中,一个数组arr,arr.tail表示除了头元素之外的其他元素,arr.zip(arr.tail)即把arr转化为(page0,page1)(page1,page2)…
package server
import commons.constant.Constants
import commons.model.UserVisitAction
import commons.utils.{DateUtils, ParamUtils}
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
class serverFive extends Serializable {
def getSkipRatio(session: SparkSession, sessionId2FilterActionRDD: RDD[(String, UserVisitAction)], taskUUID: String)={
//1.获取目表页面
val pageFlow=ParamUtils.getPageFlow();
//2.聚合用户信息,获取用户页面跳转统计---countByKey---(page1_page2, count)
val sessionId2GroupRDD=sessionId2FilterActionRDD.groupByKey();
val skipCountRDD=getPageSKipCount(session,pageFlow,sessionId2GroupRDD );
val pageSplitCountMap=skipCountRDD.countByKey();
//3.计算比列
getPagesSkipRatio(pageSplitCountMap,session,taskUUID);
}
def getPagesSkipRatio(pageSplitCountMap: collection.Map[String, Long], session: SparkSession, taskUUID: String) = {
val sum=pageSplitCountMap.values.sum.toDouble;
val ratios=pageSplitCountMap.map{
case(k,v)=>{
val ratio=v/sum;
(k,ratio);
}
}
ratios.foreach(println);
}
def getPageSKipCount(sparkSession: SparkSession,
targetPageFlow: Array[String],
sessionId2GroupRDD: RDD[(String, Iterable[UserVisitAction])]) = {
sessionId2GroupRDD.flatMap{
case(sessionId,actions)=>{
val sortedActions=actions.toList.sortWith((item1,item2)=>{
DateUtils.parseTime(item1.action_time).getTime<DateUtils.parseTime(item2.action_time).getTime;
})
val pages=sortedActions.map(item=>item.page_id);
// pageArray.slice(0, pageArray.length - 1): [1,2,3,4,5,6]
// pageArray.tail:[2,3,4,5,6,7]
// zip: (1,2),(2,3).....
val splitPages=pages.slice(0,pages.size-1).zip(pages.tail).map{
case(page1,page2)=>{
page1+"-"+page2;
}
}
val splitPagesFilter=splitPages.filter(item=>targetPageFlow.contains(item)).map(item=>(item,1L));
splitPagesFilter
}
}
}
}