Spark PV、UV分析

PV、UV分析常用于MapReduce的离线日志分析系统中,那么如果用Spark该怎么做呢?本文仅对数据进行统计进行分析,权当抛砖引玉,希望能看到大佬对其进行更深入的操作。

1、需求

根据数据计算各网站的PV,UV,同时,只显示top5(按PV值,或者UV值排序,取前5名)

2、 数据

数据是对13w+条PV、UV记录,数据的格式如下,列之间用tab分隔,如果读者感兴趣,可以点击这里下载

57.222.102.178	青海	2018-11-12	1542011090255	167000459809553480	www.baidu.com	View
57.222.102.178	青海	2018-11-12	1542011090255	167000459809553480	www.gome.com.cn	View
57.222.102.178	青海	2018-11-12	1542011090255	167000459809553480	www.taobao.com	Buy
103.190.42.13	江苏	2018-11-12	1542011090255	4152752257070526126	www.baidu.com	View
103.190.42.13	江苏	2018-11-12	1542011090255	4152752257070526126	www.suning.com	Comment
103.190.42.13	江苏	2018-11-12	1542011090255	4152752257070526126	www.taobao.com	Buy
103.190.42.13	江苏	2018-11-12	1542011090255	4152752257070526126	www.gome.com.cn	Buy
103.190.42.13	江苏	2018-11-12	1542011090255	4152752257070526126	www.gome.com.cn	Login

3、PV分析

3.1 期望得到的元素

首先我们来分析PV,我们要明确需要使用哪一列来作为我们统计的依据,既然要统计PV,那么肯定是按网址来统计,所以我们取第五列数据作为统计依据。

//读取源文件,并设置最小分区数为5(这个最小分区数是随意设的,为了提高并行度,不必纠结)
val file: RDD[String] = sc.textFile("./pvuvdata",5)

//将数据进行切割,获取第5列数据,并将其转换成("www.baidu.com",1)这样的键值对
val pair: RDD[(String, Int)] = file.map(line=>  (line.split("\t")(5),1)    )

3.2 期望统计排序的元素

我们已经得到了作为统计依据的列,现在我们需要对PV进行统计和排序,统计很好理解,就是pair.reduceByKey(_+_),但是我们要如何对value进行排序呢,Spark中并没有reduceByvalue()函数,这时我们可以转换一下思维(有经验的同学可能知道可以用sorted()函数,我们这里先不讨论),Spark中有一个SortedBykey()函数,可以直接对key进行全局排序,如果我们将(“www.baidu.com,1”)转换成(1,“www.baidu.com”),不就可以直接排序了吗?

val map: RDD[(Int, String)] = reduce.map(_.swap)
val sorted: RDD[(Int, String)] = map.sortByKey(false)

3.3 整理并打印

得到了全排序的结果,结果是(9999,“www.baidu.com”)格式的,我们需要将其转换回(“www.baidu.com”,9999)的格式,然后取前5条打印即可。

val res: RDD[(String, Int)] = sorted.map(_.swap)
val pv: Array[(String, Int)] = res.take(5)
pv.foreach(println)

3.4 PV分析代码

 def main(args: Array[String]): Unit = {

    val conf: SparkConf = new SparkConf().setMaster("local").setAppName("sort")
    val sc = new SparkContext(conf)
    sc.setLogLevel("ERROR")
    
    val file: RDD[String] = sc.textFile("bigdata-spark/data/pvuvdata",5)
    
    //  187.144.73.116	浙江	2018-11-12	1542011090255	3079709729743411785	www.jd.com	Comment
    println("----------PV:-----------")

    val pair: RDD[(String, Int)] = file.map(line=>  (line.split("\t")(5),1)    )
    val reduce: RDD[(String, Int)] = pair.reduceByKey(_+_)

    val map: RDD[(Int, String)] = reduce.map(_.swap)
    val sorted: RDD[(Int, String)] = map.sortByKey(false)
    val res: RDD[(String, Int)] = sorted.map(_.swap)
    val pv: Array[(String, Int)] = res.take(5)
    pv.foreach(println)
    }

4、UV分析

4.1 期望得到的元素

UV统计方式大体上和PV相同,但是需要注意到一点,UV统计的是不同用户访问这个网站的数量,也就是说,同一个用户可能多次访问一个网站,但是最终访问这个网站的IP只有一个,所以我们需要将网址和IP绑定在一起,然后执行去重操作,这样得到的UV才是准确的。

//  187.144.73.116	浙江	2018-11-12	1542011090255	3079709729743411785	www.jd.com	Comment

    val keys: RDD[(String, String)] = file.map(
      line => {
        val strs: Array[String] = line.split("\t")
        (strs(5), strs(0))
      }
    )
    val key: RDD[(String, String)] = keys.distinct()

4.2 期望统计排序的元素

统计排序的时候,我们只需要统计网站就行,所以我们只取(“www.baidu”,192.168.126.10)这个键值对中的第一个元素,然后对它进行排序,这里我们使用sorted()函数来进行排序,sorted()函数可以传入一个参数,指定要进行排序的value的位置。

val pairx: RDD[(String, Int)] = key.map(k => (k._1,1))
val uvreduce: RDD[(String, Int)] = pairx.reduceByKey(_+_)
val uvSorted: RDD[(String, Int)] = uvreduce.sortBy(_._2,false)

4.3 整理并打印

现在我们也得到了UV全排序的结果,直接取前5条打印即可。

val uv: Array[(String, Int)] = uvSorted.take(5)
uv.foreach(println)

4.4 UV分析代码

  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local").setAppName("sort")
    val sc = new SparkContext(conf)
    sc.setLogLevel("ERROR")

    val file: RDD[String] = sc.textFile("bigdata-spark/data/pvuvdata",5)
    //  187.144.73.116	浙江	2018-11-12	1542011090255	3079709729743411785	www.jd.com	Comment

    val keys: RDD[(String, String)] = file.map(
      line => {
        val strs: Array[String] = line.split("\t")
        (strs(5), strs(0))
      }
    )
    val key: RDD[(String, String)] = keys.distinct()
    val pairx: RDD[(String, Int)] = key.map(k => (k._1,1))
    val uvreduce: RDD[(String, Int)] = pairx.reduceByKey(_+_)
    val uvSorted: RDD[(String, Int)] = uvreduce.sortBy(_._2,false)
    val uv: Array[(String, Int)] = uvSorted.take(5)
    uv.foreach(println)
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值