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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 日志分析实战之清洗日志小实例6:获取uri点击量排序并得到最高的url

下面我们开始统计链接的点击量,并做排序。

我们统计记录的时候,为了防止空记录等异常的情况,我们创建一条空记录

val nullObject = AccessLogRecord("", "", "", "", "GET /foo HTTP/1.1", "", "", "", "")

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


首先获取我们想要的uri


val uriCounts = log.map(p.parseRecord(_).getOrElse(nullObject).request)
                  .map(_.split(" ")(1))
                  .filter(_ != "/foo")

上面的代码做一个简单解释:

p.parseRecord(_)解析记录

p.parseRecord(_).getOrElse(nullObject)如何没有取到值,则使用nullObject,也就是我们上面定义的对象

p.parseRecord(_).getOrElse(nullObject).request也就是我们取到uri

.map(_.split(" ")(1))是取到我们过滤的url,过滤掉不想要的版本等信息

 .filter(_ != "/foo")则是再次过滤掉/foo[也就是空记录]

这样就获取了uri,然后我们输出

uriCounts.collect.foreach(print)

c6adf927781e2d36359a90c9ddbef6f3.jpg

下面我们统计点击量



val uriCounts = log.map(p.parseRecord(_).getOrElse(nullObject).request)
                  .map(_.split(" ")(1))
                  .map(uri => (uri, 1))
                  .reduceByKey((a, b) => a + b)


rdd转换为数组




val uriToCount = uriCounts.collect


数组转换为序列并排序



import scala.collection.immutable.ListMap
val uriHitCount = ListMap(uriToCount.toSeq.sortWith(_._2 > _._2):_*)

12db63d9f311b7e591c2d0982b203945.jpg

#############################

这里留下一个问题,如果上面元素不是2,而是为sortWith(_._1 > _._1)是对什么排序

import scala.collection.immutable.ListMap
val uriHitCount = ListMap(uriToCount.toSeq.sortWith(_._1 > _._1):_*)

#############################

3d215861311bc5e15689c4a0f89d9bf5.jpg

输出

uriHitCount.take(10).foreach(println)

90a982b316ddbdf4e37a4b73d552881c.jpg

上面便是排序的结果

点击最高的uri
如果想得出点击最高的uri

uriHitCount.take(1).foreach(println)

563df5644efa45cd8d8a3ec05c4785c2.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中下一个元素(第三个元素)组成两个元素,再被传给输入函数,直到最后只有一个值为止。


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


具体过程,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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3月前
|
Java
【实战演练】JAVA网络编程高手养成记:URL与URLConnection的实战技巧,一学就会!
【6月更文挑战第22天】在Java网络编程中,理解和运用URL与URLConnection是关键。URL代表统一资源定位符,用于标识网络资源;URLConnection则用于建立与URL指定资源的连接。通过构造URL对象并调用openConnection()可创建URLConnection。示例展示了如何发送GET请求读取响应,以及如何设置POST请求以发送数据。GET将参数置于URL,POST将参数置于请求体。练习这些基本操作有助于提升网络编程技能。
59 3
|
8天前
|
数据采集 存储 前端开发
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
|
11天前
|
Java
【实战演练】JAVA网络编程高手养成记:URL与URLConnection的实战技巧,一学就会!
【实战演练】JAVA网络编程高手养成记:URL与URLConnection的实战技巧,一学就会!
24 3
|
15天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
27天前
|
存储 NoSQL 算法
实战算法篇:设计短域名系统,将长URL转化成短的URL.
小米介绍了一种实用的短域名系统设计,用于将冗长的URL转化为简短链接。短链接不仅节省空间,便于分享,还能支持数据分析。系统通过唯一编号结合62进制转换生成短标识,并利用如Redis这样的数据库存储长链接与短标识的映射关系。最后,通过302重定向实现用户访问时的长链接恢复。这一方案适用于多种场景,有效提升用户体验与数据追踪能力。
37 9
|
16天前
|
Kubernetes Shell 网络安全
【Azure K8S】记录AKS VMSS实例日志收集方式
【Azure K8S】记录AKS VMSS实例日志收集方式
|
17天前
|
存储 Linux 网络安全
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
|
3月前
|
运维 安全 Serverless
函数计算产品使用问题之登陆函数实例之后如何查看函数的日志
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
16天前
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
|
8天前
|
存储 监控 数据可视化
SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
【9月更文挑战第2天】SLS 虽然不是直接使用 OSS 作为底层存储,但它凭借自身独特的存储架构和功能,为用户提供了一种专业、高效的日志服务解决方案。
41 9
下一篇
DDNS