使用Scala语言操作实现Spark处理数据,实现wordcount程序;分析用户行为数据统计用户停留时间段

使用环境

Windows下使用IDEA开发工具
Windows环境配置了JDK1.8环境与Scala环境

准备事项

本文WordCount案例预实现将Linux中的HDFS中的文件读取出来
统计字符出现次数,并将结果存放到HDFS目录中

配置Hadoop环境中的权限

修改hadoop中的配置文件hdfs-site.xml
在这里插入图片描述

将Hadoop中的配置文件存放到IDEA项目中的resource中

在这里插入图片描述

IDEA中的pom.xml配置文件

使用了Maven管理依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.huadian</groupId>
    <artifactId>spark-learning</artifactId>
    <version>1.0-SNAPSHOT</version>

    <repositories>
        <repository>
            <id>aliyun</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
        <repository>
            <id>cloudera</id>
            <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
        </repository>
        <repository>
            <id>jboss</id>
            <url>http://repository.jboss.com/nexus/content/groups/public</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <hadoop.version>2.6.0-cdh5.7.6</hadoop.version>
        <spark.version>2.2.0</spark.version>
    </properties>


    <dependencies>

        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>


        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.20.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

使用SparkContext实现WordCount

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object SparkContext{
  //scala程序的入口,也是spark application运行Driver
  def main(args: Array[String]): Unit = {
    //Spark app 配置:应用的名字和Master运行的位置
    val sparkConf = new SparkConf()
      .setAppName("SparkAppTemplate")
      .setMaster("local[2]")

    //创建sparkContext对象:主要用于读取需要处理的数据,封装在RDD集合中;调度jobs执行
    val sc = new SparkContext(sparkConf)
    sc.setLogLevel("WARN")
    //第一步:数据的读取(输入)
    val inputRDD: RDD[String] = sc.textFile("/wc.input")
    println(s"count:${inputRDD.count()}")
    println(s"first:${inputRDD.first()}")

    //第二步:数据的处理(分析)
    //分割 ->(key,1) ->分组
    val wordCountRDD: RDD[(String, Int)] = inputRDD
      //.flatMap(item => item.split(" "))
      .flatMap(_.split(" "))
      //.map(word =>(word,1))
      .map((_,1))
      //.reduceByKey((a,b)=>a+b)
      .reduceByKey(_ + _)

    //第三步:数据的输出(输出)
    wordCountRDD.foreach(println)
    wordCountRDD.saveAsTextFile("/wc-output/"+System.currentTimeMillis())

    //inputRDD.unpersist()
    //开发测试的时候,为了对每个spark app页面监控查看job的执行情况,
    //spark app运行结束4040端口就没了
    //关闭资源
    sc.stop()
  }
}

使用SparkSession实现WordCount

package com.huadian.bigdata.spark.core

import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{Dataset, SparkSession}
import org.apache.spark.{SparkConf, SparkContext}

/**
  * Spark Application开发模板
  */
object SparkSessionWordCount {
  //scala程序的入口,也是spark application运行Driver
  def main(args: Array[String]): Unit = {

    //在spark 2.x中不推荐使用sparkContext对象读取数据,而是推荐SparkSession
    val spark = SparkSession.builder
      .appName("Simple Application")
      .master("local[2]")
      .getOrCreate()
	  //设置日志级别
    spark.sparkContext.setLogLevel("WARN")

    //第一步:数据的读取(输入)
    //DataSet = RDD + schema
    //如果RDD是一个人的话,到底有什么属性,我们是不知道的,只有执行的时候才知道
    //如果是DataSet的话,有name,age字段,以及对应数据类型
    val inputRDD: RDD[String] = spark.read.textFile("/wc.input").rdd


    //第二步:数据的处理(分析)
    val wordCountRDD: RDD[(String, Int)] = inputRDD.flatMap(_.split(" ")).map((_,1)).reduceByKey(_ + _)

    //第三步:数据的输出(输出)
    wordCountRDD.foreach(println)
    println("===========输出前三方式1==========")
    wordCountRDD
      .map(tuple=>tuple.swap)
      //.map(_.swap)
      .top(3)
      .foreach(println)

    println("=======输出前三方式2===========")
    wordCountRDD
      .top(3)(OrderUtils.SecondValueOrder)
      .foreach(println)

    //开发测试的时候,为了对每个spark app页面监控查看job的执行情况,
    //spark app运行结束4040端口就没了

    //关闭资源
    spark.stop()
  }
  object OrderUtils{
    object SecondValueOrder extends scala.math.Ordering[(String,Int)]{
      override def compare(x: (String, Int), y: (String, Int)): Int = x._2 - y._2
    }
  }
}

案例:用户行为数据行为分析

本案例运行在Windows环境下,IDEA中

数据格式

第一项为用户访问时间
第二项为用户访问网址
第三项为用户会话id

2013-05-19 13:00:00	http://www.taobao.com/17/?tracker_u=1624169&type=1	B58W48U4WKZCJ5D1T3Z9ZY88RU7QA7B1

实现思路

第一步,读取数据文件
第二步:处理数据文件
第三步:提取时间数据与用户会话id数据
第四步:按照用户会话id分组,键为用户会话id,值为访问时间
第五步:计算会话时间,判断用户停留时间区间,返回用户停留时间区间,键为用户停留时间,值为1
第六步:按照用户停留时间区间进行聚合统计用户停留时间区间
第七步:输出结果

代码实现

import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.{SparkConf, SparkContext}

object SparkApp2 {
  val TIME_LENGTH_0010:String = "0-10"
  val TIME_LENGTH_1120:String = "11-20"
  val TIME_LENGTH_2130:String = "21-30"
  val TIME_LENGTH_3000:String = "30++"
  def main(args: Array[String]): Unit = {

    //在spark 2.x中不推荐使用sparkContext对象读取数据,而是推荐SparkSession
    val spark = SparkSession.builder
      .appName("Simple Application")
      .master("local[2]")
      .getOrCreate()
    spark.sparkContext.setLogLevel("WARN")

    //第一步:数据的读取(输入)
    //DataSet = RDD + schema
    //如果RDD是一个人的话,到底有什么属性,我们是不知道的,只有执行的时候才知道
    //如果是DataSet的话,有name,age字段,以及对应数据类型
    //    第一步,读取数据文件
    val first: RDD[String] =  spark.read.textFile("file:///E:\\JavaWork\\20190801\\page_views.data").rdd

    //    第二步:处理数据文件

    val second: RDD[(String, Long)] = first.map{
      //    第三步:提取时间数据与用户会话id数据
      line=>{
        val arr: Array[String] = line.split("\t")
        import java.text.SimpleDateFormat
        //获取时间,为时间戳格式,方便运算
        val time: Long = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(arr(0)).getTime
        //返回值
        (arr(2),time)
      }
    }
//    第四步:按照用户会话id分组,键为用户会话id,值为访问时间
    val fourth: RDD[(String, Iterable[Long])] = second.groupByKey()
//    第五步:计算会话时间,判断用户停留时间区间,返回用户停留时间区间,键为用户停留时间,值为1
    val fifth: RDD[(String, Int)] = fourth.map{
      case (sessionId:String,iter:Iterable[Long])=>{
        //最大的访问时间
        val maxTackTime = iter.max
        //最小的访问时间
        val minTackTime = iter.min
        //访问的会话时间
        val timeLength = (maxTackTime - minTackTime)/1000.0
        if(timeLength >30){
          (TIME_LENGTH_3000,1)
        }else if (timeLength >20){
          (TIME_LENGTH_2130,1)
        }else if (timeLength >10){
          (TIME_LENGTH_1120,1)
        }else{
          (TIME_LENGTH_0010,1)
        }
      }
    }
//    第六步:按照用户停留时间区间进行聚合统计用户停留时间区间
    val sixth: RDD[(String, Int)] = fifth.reduceByKey(_+_)
//    第七步:输出结果
    sixth.foreach(println)
    //输出各个RDD的依赖关系
    println(sixth.toDebugString)
    Thread.sleep(1000000000)
    //关闭资源
    spark.stop()
  }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无名一小卒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值