用户访问量的统计时,遇到字段位数不同意时怎么处理?

实际的业务中,我们要统计访问量,必然是统计IP字段,但是拿到的数据可能是这样子的:
"27.38.5.159" "-" "31/Aug/2015:00:04:37 +0800" "GET /course/view.php?id=27 HTTP/1.1" "303" "440" - "http://www.ibeifeng.com/user.php?act=mycourse" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" "-" "learn.ibeifeng.com"

"27.38.5.159" "-" "31/Aug/2015:00:04:53 +0800" "GET /theme/image.php/bootstrap/core/1427679483/i/grades HTTP/1.1" "200" "912" - "http://learn.ibeifeng.com/course/view.php?id=27" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" "-" "learn.ibeifeng.com"

"219.135.107.124" "-" "31/Aug/2015:02:13:56 +0800" "GET /mod/page/view.php?id=11152&section=4 HTTP/1.1" "200" "9784" - "http://learn.ibeifeng.com/mod/page/view.php?id=11154&section=4" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240 QQBrowser/8.3.4769.400" "-" "learn.ibeifeng.com"

"60.30.29.146" "-" "31/Aug/2015:07:40:26 +0800" "GET /course/view.php?id=16 HTTP/1.1" "303" "440" - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36" "-" "learn.ibeifeng.com"
观察发现,如果要切分,我们可以使用空格把每个字段且分开来,从而得到IP,不错实际得到的IP字段如下:
"27.38.5.159"
"27.38.5.159"
"219.135.107.124"
"60.30.29.146"

IP是出来了,但是每个IP会有双引号,这显然不是我们想要的这样:

27.38.5.159
27.38.5.159
219.135.107.124
60.30.29.146

怎样做到呢?

有人想到用substring()进行截取,代码如下:

val ip = strings(0).substring(1, 12)

但是问题又来了,第一条数据和第二条数据位数和格式上一样子的,IP是从1-12,没有问题,但是第三条第四条数据显然不适用了,第三条的IP超出了12,这一来,我们得到的IP就不全:如下:

27.38.5.159
27.38.5.159
219.135.107
60.30.29.14

看到,IP不去全了,怎么解决?

在我的灵机一动下,想到了如下的解决办法?

还是同样的方法,但是end位置变一下:

 val ip = strings(0).substring(1, strings(0).length-1)

将substring(1,12)中,end换成(strings(0).length-1),这样是根据截取的字符的下标通过length-1获取最后一位,做的好处就是不管有多少位,都会动态的获取最后一位下表,并截取出来。

如此,解决这样的问题,但是我们可发现,利用下标,效率会慢很多,但是能够解决问题处理少量的数据,还是可以的。

完整的代码如下:

package spark.core

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
import spark.core.TimeUtil.{NumberUtil, TimeRangeUtil}

/**
 * @className: spark.core.WebLOgAndLysis
 * @author: Star
 * @create: 2022-07-21 16:15
 *          Description:
 *          用户访问量的TOP10;
 *          以半小时为单位统计用户的人们访问时段。
 */
object WebLOgAndLysis {

  /**
   * 数据清洗和字段提取;
   *
   * @param rdd 原始的日志数据
   * @return 清洗后的RDD(ip,dt,statue)
   */
  def extract(rdd: RDD[String]): RDD[(String, String, String)] = {
    rdd.map(line => {
      val strings = line.split(" ")
      val ip = strings(0).substring(1, strings(0).length - 1)
      val time = strings(2).substring(13, 18)
      val dt = TimeRangeUtil.toHalfHourRange(time)
     
      val statue = strings(7).substring(1, 4)
      (ip, dt, statue)
    })
      .filter(_._3.equals("200"))
  }

  def main(args: Array[String]): Unit = {
    //ETL操作
    //程序入口
    val conf = new SparkConf()
      .setMaster("local[2]")
      .setAppName("WebLOgAndLysis")
    val sc = new SparkContext(conf)

    //读取文件
    val rdd = sc.textFile("G:\\MyWoekSpease\\hadoop-test\\moodle.access.log")

    //调用extract传入文件
    val extractedRDD: RDD[(String, String, String)] = extract(rdd)
    extractedRDD.foreach(println(_))
  }
}

封装的处理时间的方法:

package spark.core.TimeUtil

/**
 * @className: spark.core.TimeUtil.TimeRangeUtil
 * @author: Star
 * @create: 2022-07-21 16:40
 */
object TimeRangeUtil {
  def toHalfHourRange(str: String): String = {
    val strings = str.split(":")
    var minute = strings(1)
    minute = if (minute.toInt >= 30) "30" else "00"
    strings(0) + ":" + minute
  }

}

至此,欢迎更好的想法来讨论。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值