Imooc网主站日志介绍:
- 访问时间
- 访问url
- 访问过程耗费的流量
- 访问ip地址
第一步是数据清洗:
一般的日志处理方式,我们是需要进行分区的,
按照日志中的访问时间进行相应的分区,比如:d,h,m5(每5分钟一个分区)
输入:访问时间、访问URL、耗费的流量、访问IP地址信息
输出:URL、cmsType(video/article)、cmsId(编号)、流量、ip、城市信息、访问时间、天
利用spark分析慕课网5G日志实战项目一:https://blog.csdn.net/qq_41479464/article/details/98211937
- 项目需求:
-
课程视频及所有资料和代码以及镜像链接:
实战一的链接包括基本操作:https://blog.csdn.net/qq_41479464/article/details/98212216
整体三个代码:如箭头所指
需求二:按照地理位置(跟据IP地址提取出城市信息)(地市)(窗口函数在SparkSql中的使用)统计imooc的主站最受欢迎的课程/或手记的TopN访问次数
数据类型:
定义一个scala类:DayCityVideoAccessStat
package log
case class DayCityVideoAccessStat(day:String, cmsId:Long, city:String,times:Long,timesRank:Int)
定义一个StatDao层留把数据存放进数据库中:
package log
import java.sql.{Connection, PreparedStatement}
import scala.collection.mutable.ListBuffer
/**
* 各个维度统计的Dao操作
*/
object StatDao {
/**
* 批量保存到DayVideoAccessStat数据库中
*
*/
/**
* 批量保存DayVideoAccessStat到数据库
*/
def insertDayVideoAccessTopN(list: ListBuffer[DayVideoAccessStat]): Unit = {
var connection: Connection = null
var pstmt: PreparedStatement = null
try {
connection = MysqlUtils.getConnection()
connection.setAutoCommit(false) //设置手动提交
val sql = "insert into day_video_access_topn_stat(day,cms_id,times) values (?,?,?) "
pstmt = connection.prepareStatement(sql)
for (ele <- list) {
pstmt.setString(1, ele.day)
pstmt.setLong(2, ele.cmsId)
pstmt.setLong(3, ele.times)
pstmt.addBatch()
}
pstmt.executeBatch() // 执行批量处理
connection.commit() //手工提交
} catch {
case e: Exception => e.printStackTrace()
} finally {
MysqlUtils.release(connection,pstmt)
}
}
}
定义作业:
TopNStatJob2:类
package log
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.sql.functions._
import scala.collection.mutable.ListBuffer
object TopNStatJob2 {
/**
* TopN统计spark作业
*/
def main(args: Array[String]) {
val spark = SparkSession.builder().appName("TopNStatJob2")
.config("spark.sql.sources.partitionColumnTypeInference.enabled", false)
.master("local[2]").getOrCreate()
val accessDF = spark.read.format("parquet").load("D:\\BigDataTest\\data\\clean")
accessDF.printSchema()
accessDF.show()
/**
* 按照地市统计topN的课程
*
*/
cityAccessTopNStat(spark,accessDF)
spark.stop()
}
/**
* 按照地市进行统计
* accessDF
*/
/**
* 按照地市进行统计TopN课程
*/
def cityAccessTopNStat(spark: SparkSession, accessDF:DataFrame): Unit = {
import spark.implicits._
// //过滤出当天的视频的个数
val cityAccessTopNDF = accessDF.filter($"day"==="20170511" && $"cmsType"==="video")
.groupBy("day","city","cmsId")
.agg(count("cmsId").as("times"))
//cityAccessTopNDF.show(false)
//Window函数在Spark SQL的使用
val top3DF = cityAccessTopNDF.select(
cityAccessTopNDF("day"),
cityAccessTopNDF("city"),
cityAccessTopNDF("cmsId"),
cityAccessTopNDF("times"),
row_number().over(Window.partitionBy(cityAccessTopNDF("city"))
.orderBy(cityAccessTopNDF("times").desc)
).as("times_rank")
).filter("times_rank <=3")//.show(false) //Top3
/**
* 将统计结果写入到MySQL中
*/
try {
top3DF.foreachPartition(partitionOfRecords => {
val list = new ListBuffer[DayCityVideoAccessStat]
partitionOfRecords.foreach(info => {
val day = info.getAs[String]("day")
val cmsId = info.getAs[Long]("cmsId")
val city = info.getAs[String]("city")
val times = info.getAs[Long]("times")
val timesRank = info.getAs[Int]("times_rank")
list.append(DayCityVideoAccessStat(day,cmsId,city,times,timesRank))
})
StatDao2.insertDayCityVideoAccessTopN(list)
})
} catch {
case e:Exception => e.printStackTrace()
}
}
}
最后得到的某天的数据:
数据可视化的过程:在项目实战一中有基础可视化的教程的介绍:这里面我用的Zeppelin
实战一的链接包括基本操作:https://blog.csdn.net/qq_41479464/article/details/98212216