Spark对数据日志进行清洗

样例数据(取一行)

2018-09-04T20:27:31+08:00	http://datacenter.bdqn.cn/logs/user?actionBegin=1536150451540&actionClient=Mozilla%2F5.0+%28Windows+NT+10.0%3B+WOW64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F58.0.3029.110+Safari%2F537.36+SE+2.X+MetaSr+1.0&actionEnd=1536150451668&actionName=startEval&actionTest=0&actionType=3&actionValue=272090&clientType=001_kgc&examType=001&ifEquipment=web&isFromContinue=false&skillIdCount=0&skillLevel=0&testType=jineng&userSID=B842B843AE317425D53D0C567A903EF7.exam-tomcat-node3.exam-tomcat-node3&userUID=272090&userUIP=1.180.18.157	GET	200	192.168.168.64	-	-	Apache-HttpClient/4.1.2 (java 1.5)

具体实现如下

package kb11.ed

import java.util.Properties

import org.apache.commons.lang.StringUtils
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql._
import org.apache.spark.sql.functions._
object EtlDemo {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("etldemo")
    val spark: SparkSession = SparkSession.builder().config(conf).getOrCreate()
    val sc: SparkContext = spark.sparkContext

    import spark.implicits._
   // 加载日志数据,按照\t分割,过滤出长度为8的数据,将数据封装到Row中
 val rowRdd: RDD[Row] = sc.textFile("inpath/test.log").map(x => x.split("\t"))
      .filter(_.length == 8).map(x => Row(x(0), x(1), x(2), x(3), x(4), x(5), x(6), x(7)))
      
      val long_schame: StructType = StructType(Array(
      StructField("event_time", StringType),
      StructField("url", StringType),
      StructField("method", StringType),
      StructField("status", StringType),
      StructField("sip", StringType),
      StructField("user_uip", StringType),
      StructField("action_prepend", StringType),
      StructField("action_client", StringType)
    ))
    val logDF: DataFrame = spark.createDataFrame(rowRdd,long_schame)
    
//去除重复的event_time,url列,过滤出状态为200的数据,除去event_time为空的数据
	val fiterLogs: Dataset[Row] = logDF.dropDuplicates("event_time", "url")
      .filter(x => x(3) == "200")
      .filter(x => StringUtils.isNotEmpty(x(0).toString))
val full_logs_RDD: RDD[Row] = fiterLogs.map(line => {
      val str = line.getAs[String]("url")
      val paramsArray= str.split("\\?")
      var paramsMap: Map[String, String] = null
      if (paramsArray.length == 2) {
        val strings = paramsArray(1).split("&")
        paramsMap = strings.map(x => x.split("=")).filter(x => x.length == 2)
          .map(x => (x(0), x(1))).toMap
      }
      ( //最好不要超过22个,如果非要那么多,建议使用元组中套元组
        line.getAs[String]("event_time"),
        paramsMap.getOrElse[String]("userUID", ""),
        paramsMap.getOrElse[String]("userSID", ""),
        paramsMap.getOrElse[String]("actionBegin", ""),
        paramsMap.getOrElse[String]("actionEnd", ""),
        paramsMap.getOrElse[String]("actionType", ""),
        paramsMap.getOrElse[String]("actionName", ""),
        paramsMap.getOrElse[String]("actionValue", ""),
        paramsMap.getOrElse[String]("actionTest", ""),
        paramsMap.getOrElse[String]("ifEquipment", ""),
        line.getAs[String]("method"),
        line.getAs[String]("status"),
        line.getAs[String]("sip"),
        line.getAs[String]("user_uip"),
        line.getAs[String]("action_prepend"),
        line.getAs[String]("action_client")
      )
    }).toDF().rdd
    
	val full_logs_schema = StructType(
      Array(
        StructField("event_time",StringType),

        StructField("userUID",StringType),
        StructField("userSID",StringType),
        StructField("actionBegin",StringType),
        StructField("actionEnd",StringType),
        StructField("actionType",StringType),
        StructField("actionName",StringType),
        StructField("actionValue",StringType),
        StructField("actionTest",StringType),
        StructField("ifEquipment",StringType),

        StructField("method",StringType),
        StructField("status",StringType),
        StructField("sip",StringType),
        StructField("user_uip",StringType),
        StructField("action_prepend",StringType),
        StructField("action_client",StringType)
      )
    )
    val full_logDF = spark.createDataFrame(full_logs_RDD,full_logs_schema)
    full_logDF.printSchema()
    full_logDF.show(10)
    //连接Mysql,将数据存入其中
    val url = "jdbc:mysql://192.168.119.125:3306/etl"
    val user = "root"
    val password = "ok"
    val driver = "com.mysql.jdbc.Driver"

    val properties = new Properties()
    properties.setProperty("url",url)
    properties.setProperty("user",user)
    properties.setProperty("password",password)
    properties.setProperty("driver",driver)
    //写入Mysql
    println("将filterlogs写入Mysql")

    fiterLogs.write.mode("Overwrite").jdbc(url,"access_logs",properties)

    println("写入完成")

    println("写入full_logDF到数据库")
    full_logDF.write.mode(SaveMode.Append).jdbc(jdbcUntils.url,jdbcUntils.table_full_access_log,properties)
    println("写入full_logDF到数据库完成")
    spark.stop()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark离线数据清洗可以使用SparkSQL和DataFrame API来实现。具体步骤如下: 1.读取数据:使用SparkContext的textFile()方法读取数据文件,返回一个RDD[String]类型的对象。 2.将RDD[String]转换为DataFrame:使用SparkSession的createDataFrame()方法将RDD[String]转换为DataFrame类型的对象。 3.过滤数据:使用DataFrame API中的filter()方法过滤掉不符合条件的数据。 4.处理数据:使用DataFrame API中的各种方法对数据进行处理,例如使用withColumnRenamed()方法重命名列名,使用drop()方法删除不需要的列等。 5.保存数据:使用DataFrame API中的write()方法将处理后的数据保存到指定的文件中。 下面是一个示例代码,假设我们有一个日志文件test.log,其中每行数据由8个字段组成,字段之间使用制表符分隔: ```scala import org.apache.spark.sql.{Row, SparkSession} val spark = SparkSession.builder() .appName("Data Cleaning") .master("local[*]") .getOrCreate() // 读取数据 val linesRDD = spark.sparkContext.textFile("test.log") // 将RDD[String]转换为RDD[Row]的形式,并过滤字段数少于8的日志 val rowRDD = linesRDD.map(_.split("\t")) .filter(_.length == 8) .map(x => Row(x(0).trim, x(1).trim, x(2).trim, x(3).trim, x(4).trim, x(5).trim, x(6).trim, x(7).trim)) // 定义DataFrame的schema val schema = spark.read .option("header", "true") .option("inferSchema", "true") .csv("test.log") .schema // 将RDD[Row]转换为DataFrame val df = spark.createDataFrame(rowRDD, schema) // 对数据进行处理 val cleanedDF = df .withColumnRenamed("col1", "new_col1") .drop("col2") // 保存数据 cleanedDF.write .option("header", "true") .csv("cleaned_data") ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值