hive视频热度统计案例
背景及需求描述
现有两个记录了关于youtube视频信息和用户信息的txt文件
其中存放了视频信息的文件每行的字段如下所示:
字段 | 备注 | 详细描述 |
---|---|---|
video id | 视频唯一 id | 11 位字符串 |
uploader | 视频上传者 | 上传视频的用户名 String |
age | 视频年龄 | 视频在平台上的整数天 |
category | 视频类别 | 上传视频指定的视频分类 |
length | 视频长度 | 整形数字标识的视频长度 |
views | 观看次数 | 视频被浏览的次数 |
rate | 流量 | 视频的流量,整型数字 |
conments | 评论数 | 一个视频的整数评论数 |
related ids | 相关视频 id | 相关视频的 id,最多 20 个 |
存放了用户信息的文件每行字段如下所示:
字段 | 备注 | 字段类型 |
---|---|---|
uploader | 上传者用户名 | string |
videos | 上传视频数 | int |
friends | 朋友数量 | int |
希望根据这两个文件所包含的信息,统计硅谷影音视频网站的常规指标,各种 TopN 指标:
-
统计视频观看数 Top10
-
统计视频类别热度 Top10
-
统计视频观看数 Top20 所属类别以及类别包含的 Top20 的视频个数
-
统计视频观看数 Top50 所关联视频的所属类别 Rank
-
统计每个类别视频观看数 Top10
-
统计上传视频最多的用户 Top10 以及他们上传的观看次数在前 20 视频
项目的完成
1. 数据清洗
通过观察原始数据形式,可以发现,视频可以有多个所属分类,每个所属分类用&符号分割,且分割的两边有空格字符,同时相关视频也是可以有多个元素,多个相关视频又用“\t”进行分割。为了分析数据时方便对存在多个子元素的数据进行操作,我们首先进行数据重组清洗操作。即:将所有的类别用“&”分割,同时去掉两边空格,多个**相关视频 id 也使用“&”**进行分割。
(1) 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.atguigu</groupId>
<artifactId>guli-video</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>
</project>
(2)ETLUtils-处理具体的数据清洗逻辑
package com.atguigu.util;
import sun.security.krb5.internal.ETypeInfo;
public class ETLUtils {
/**
* 过滤每条输入数据
* 1. 过滤小于9个字段的
* 2. 去掉类别字段中的空格
* 3. 修改相关视频ID字段的分隔符,由'\t'替换为'&'
* @param oriStr 输入参数,原始数据
* @return 过滤后的数据
*/
public static String etLString(String oriStr){
StringBuffer sb = new StringBuffer();
//1.切割拿到素有字符
String[] fields = oriStr.split("\t");
//2. 根据字段数量进行过滤
if (fields.length<9){
return null;
}
//3. 去掉类别中的空格
fields[3] = fields[3].replaceAll(" ", "");
//4. 修改相关视频ID字段分隔符,由'\t'替换为'&'
for (int i = 0; i < fields.length; i++) {
//对非相关ID字段进行处理
if (i<9){
if (i==fields.length-1){
sb.append(fields[i]);
}else {
sb.append(fields[i]).append("\t");
}
}else {
//对相关ID字段进行处理
if (i==fields.length-1){
sb.append(fields[i]);
}else {
sb.append(fields[i]).append("&");
}
}
}
//5. 返回新的结果
return sb.toString();
}
/*测试
public static void main(String[] args) {
// System.out.println(ETLUtils.etLString("LKh7zAJ4nwo\tTheReceptionist\t653\tEntertainment\t424\t13021\t4.34\t1305\t744\tDjdA-5oKYFQ\tNxTDlnOuybo\tc-8VuICzXtU\tDH56yrIO5nI\tW1Uo5DQTtzc\tE-3zXq_r4w0\t1TCeoRPg5dE\tyAr26YhuYNY\t2ZgXx72XmoE\t-7ClGo-YgZ0\tvmdPOOd6cxI\tKRHfMQqSHpk\tpIMpORZthYw\t1tUDzOp10pk\theqocRij5P0\t_XIuvoH6rUg\tLGVU5DsezE0\tuO2kj6_D8B4\txiDqywcDQRM\tuX81lMev6_o"));
System.out.println(ETLUtils.etLString("SDNkMu8ZT68\tw00dy911\t630\tPeople & Blogs\t186\t10181\t3.49\t494"));
}
*/
}
(3)ETLMapper
package com.atguigu.ETL;
import com.atguigu.util.ETLUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
//清洗数据
public class ETLMapper extends Mapper<LongWritable,Text,NullWritable,Text>{
//定义全局的value
private Text v=new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//1. 获取数据
String ori = value.toString();
//2. 过滤数据
String etlStr = ETLUtils.etLString(ori);
//3. 写出数据
if (etlStr==null){
return;
}
v.set(etlStr);
context.write(NullWritable.get(),v);
}
}
(4) ETLDriver
package com.atguigu.ETL;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class