日志分析实战之清洗日志小实例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日志并进行多维度分析。
目录
相关文章
|
C++ 开发者 Python
实现Python日志点击跳转到代码位置的方法
本文介绍了如何在Python日志中实现点击跳转到代码位置的功能,以提升调试效率。通过结合`logging`模块的`findCaller()`方法记录代码位置信息,并使用支持点击跳转的日志查看工具(如VS Code、PyCharm),开发者可以从日志直接点击链接定位到出错代码,加快问题排查。
|
分布式计算 DataWorks 关系型数据库
DataWorks操作报错合集之在DataWorks中设置了一个任务节点的调度时间,并将其发布到生产环境,但到了指定时间(例如17:30)却没有产生运行实例和相关日志如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
226 0
|
9月前
|
数据采集 机器学习/深度学习 存储
使用 Python 清洗日志数据
使用 Python 清洗日志数据
143 2
|
10月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
130 2
|
11月前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
Java应用结构规范问题之AllLoggers接口获取异常日志的Logger实例的问题如何解决
|
11月前
|
Kubernetes Shell 网络安全
【Azure K8S】记录AKS VMSS实例日志收集方式
【Azure K8S】记录AKS VMSS实例日志收集方式
|
11月前
|
存储 Linux 网络安全
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
|
运维 安全 Serverless
函数计算产品使用问题之登陆函数实例之后如何查看函数的日志
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
10月前
|
前端开发 JavaScript
前端JS截取url上的参数
文章介绍了两种前端JS获取URL参数的方法:手动截取封装和使用URLSearchParams。
145 0
|
11月前
|
开发框架 前端开发 .NET
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
137 0