做什麼?
我們需要去分析每一次的頁面訪問流程,也就是用戶從進入網站到離開網站這個流程中所訪問的頁面順序,也就是一個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
}
}
}
}