分享

日志分析实战之清洗日志小实例6:获取uri点击量排序并得到最高的url

问题导读

1.读取日志的过程中,发生异常本文是如何解决的?
2.读取后,如何过滤异常的记录?
3.如何实现统计点击最高的记录?






日志分析实战之清洗日志小实例5:实现获取不能访问url
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22911


下面我们开始统计链接的点击量,并做排序。
我们统计记录的时候,为了防止空记录等异常的情况,我们创建一条空记录

[mw_shl_code=bash,true]val nullObject = AccessLogRecord("", "", "", "", "GET /foo HTTP/1.1", "", "", "", "")
[/mw_shl_code]

下面我们开始找点击量最高的链接。

首先获取我们想要的uri
[mw_shl_code=scala,true]val uriCounts = log.map(p.parseRecord(_).getOrElse(nullObject).request)
                  .map(_.split(" ")(1))
                  .filter(_ != "/foo")
[/mw_shl_code]上面的代码做一个简单解释:
p.parseRecord(_)解析记录
p.parseRecord(_).getOrElse(nullObject)如何没有取到值,则使用nullObject,也就是我们上面定义的对象
p.parseRecord(_).getOrElse(nullObject).request也就是我们取到uri
.map(_.split(" ")(1))是取到我们过滤的url,过滤掉不想要的版本等信息
  .filter(_ != "/foo")则是再次过滤掉/foo[也就是空记录]
这样就获取了uri,然后我们输出[mw_shl_code=scala,true]uriCounts.collect.foreach(print)[/mw_shl_code]

scala输出url.jpg

下面我们统计点击量
[mw_shl_code=scala,true]val uriCounts = log.map(p.parseRecord(_).getOrElse(nullObject).request)
                  .map(_.split(" ")(1))
                  .map(uri => (uri, 1))
                  .reduceByKey((a, b) => a + b)[/mw_shl_code]

rdd转换为数组
[mw_shl_code=scala,true]val uriToCount = uriCounts.collect [/mw_shl_code]

数组转换为序列并排序
[mw_shl_code=scala,true]import scala.collection.immutable.ListMap
val uriHitCount = ListMap(uriToCount.toSeq.sortWith(_._2 > _._2):_*) [/mw_shl_code]
listmap.jpg

#############################
这里留下一个问题,如果上面元素不是2,而是为sortWith(_._1 > _._1)是对什么排序
[mw_shl_code=scala,true]import scala.collection.immutable.ListMap
val uriHitCount = ListMap(uriToCount.toSeq.sortWith(_._1 > _._1):_*) [/mw_shl_code]#############################
对比.jpg

输出
[mw_shl_code=scala,true]uriHitCount.take(10).foreach(println)
[/mw_shl_code]
输出结果.jpg

上面便是排序的结果
点击最高的uri
如果想得出点击最高的uri[mw_shl_code=scala,true] uriHitCount.take(1).foreach(println)[/mw_shl_code]

点击率最高.jpg
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

知识补充:
Scala代码看上去很少,但是内容却是很丰富的。上面用到的相关知识,这里补充,供大家能看懂上面代码

getOrElse:
println(a.get("k1").getOrElse("default")) //根据key读取元素,不存在就替换成默认值

在Spark中写法是:persons.getOrElse("Spark",1000) //如果persons这个Map中包含有Spark,取出它的值,如果没有,值就是1000。



reduce、reduceByKey

reduce(binary_function)
reduce将RDD中元素前两个传给输入函数,产生一个新的return值,新产生的return值与RDD中下一个元素(第三个元素)组成两个元素,再被传给输入函数,直到最后只有一个值为止。

[mw_shl_code=scala,true]val c = sc.parallelize(1 to 10)
c.reduce((x, y) => x + y)//结果55[/mw_shl_code]

具体过程,RDD有1 2 3 4 5 6 7 8 9 10个元素,
1+2=3
3+3=6
6+4=10
10+5=15
15+6=21
21+7=28
28+8=36
36+9=45
45+10=55

reduceByKey(binary_function)
reduceByKey就是对元素为KV对的RDD中Key相同的元素的Value进行binary_function的reduce操作,因此,Key相同

的多个元素的值被reduce为一个值,然后与原RDD中的Key组成一个新的KV对。
val a = sc.parallelize(List((1,2),(1,3),(3,4),(3,6)))
a.reduceByKey((x,y) => x + y).collect
//结果 Array((1,5), (3,10))


Seq

Sequence都有一个预定义的顺序。
scala> Seq(1, 1, 2)
res3: Seq[Int] = List(1, 1, 2)
(注意返回的结果是一个List。Seq是一个trait;List是它的一个实现类。Seq对象是一个工厂对象,正如你所看到

的,它会创建一个List。)

集合之间可以相互进行转换。
def toArray : Array[A]
def toArray [B >: A] (implicit arg0: ClassManifest[B]) : Array[B]
def toBuffer [B >: A] : Buffer[B]
def toIndexedSeq [B >: A] : IndexedSeq[B]
def toIterable : Iterable[A]
def toIterator : Iterator[A]
def toList : List[A]
def toMap [T, U] (implicit ev: <:<[A, (T, U)]) : Map[T, U]
def toSeq : Seq[A]
def toSet [B >: A] : Set[B]
def toStream : Stream[A]
def toString () : String
def toTraversable : Traversable[A]

我们可以把一个Map转换成一个数组,然后得到一个键值对数组。

scala> Map(1 -> 2).toArray
res41: Array[(Int, Int)] = Array((1,2))

sortWith
排序操作(sorted, sortWith, sortBy)根据不同的条件对序列元素进行排序。更多排序内容推荐参考
Scala的map实现key和value排序及各种排序比较等知识讨论
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22942


更多大家可以搜索

相关文章:

日志分析实战之清洗日志小实例1:使用spark&Scala分析Apache日志
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22856

日志分析实战之清洗日志小实例2:导入日志清洗代码并打包
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22862


日志分析实战之清洗日志小实例3:如何在spark shell中导入自定义包
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22881



日志分析实战之清洗日志小实例4:统计网站相关信息
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22900


日志分析实战之清洗日志小实例5:实现获取不能访问url
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22911


日志分析实战之清洗日志小实例6:获取uri点击量排序并得到最高的url
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22928


日志分析实战之清洗日志小实例7:查看样本数据,保存统计数据到文件
http://www.aboutyun.com/forum.php?mod=viewthread&tid=22953


链接:http://pan.baidu.com/s/1pKXn8Ob 密码:yndp





本帖被以下淘专辑推荐:

已有(2)人评论

跳转到指定楼层
monik 发表于 2017-10-17 09:22:48
写的很不错,抽空得好好把楼主的帖子看一看!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条