Cris 小哥哥的大数据项目之 Hive 统计 YouTube 热门视频
Author:Cris
1. 项目需求
统计 YouTube 网站的常规指标,各种TopN指标:
–统计视频观看数Top10
–统计视频类别热度Top10
–统计视频观看数Top20所属类别
–统计视频观看数Top50所关联视频的所属类别Rank
–统计每个类别中的视频热度Top10
–统计每个类别中视频流量Top10
–统计上传视频最多的用户Top10以及他们上传的视频
–统计每个类别视频观看数Top10
2. 表结构和 ETL
2.1 表结构
- 视频表
字段 | 备注 | 详细描述 |
---|---|---|
video id | 视频唯一id | 11位字符串 |
uploader | 视频上传者 | 上传视频的用户名String |
age | 视频年龄 | 视频在平台上的整数天 |
category | 视频类别 | 上传视频指定的视频分类 |
length | 视频长度 | 整形数字标识的视频长度 |
views | 观看次数 | 视频被浏览的次数 |
rate | 视频评分 | 满分5分 |
Ratings | 流量 | 视频的流量,整型数字 |
conments | 评论数 | 一个视频的整数评论数 |
related ids | 相关视频id | 相关视频的id,最多20个 |
其中 related ids 有可能为空(新上传的视频也来不及通过数据分析为其添加相关视频)
- 用户表
字段 | 备注 | 字段类型 |
---|---|---|
uploader | 上传者用户名 | string |
videos | 上传视频数 | int |
friends | 朋友数量 | int |
2.2 ETL 原始数据
通过观察原始数据形式,可以发现,视频可以有多个所属分类,每个所属分类用&符号分割,且分割的两边有空格字符,同时相关视频也是可以有多个元素,多个相关视频又用“\t”进行分割。为了分析数据时方便对存在多个子元素的数据进行操作,我们首先进行数据重组清洗操作。即:将所有的类别用“&”分割,同时去掉两边空格,多个相关视频id也使用“&”进行分割
原始数据示例如下:
第四列表示类别,需要 ETL 将空格去掉;然后是第十列数据表示关联的视频 id,同样需要 ETL 将 \t 分割符变为指定的分隔符
2.3 开启 IDEA 完成 ETL 代码
写我们的 ETL 代码之前,需要明白数据清洗的目的,即需要将原数据按照怎么样的规则来进行清洗,这才是 ETL 的重点,只有清晰明了 原材料
和 最终产品
之间的关系,才会很快速的完成 ETL 代码的编写
- Mapper 阶段
ETL 一般都是使用 Mapper 阶段来对我们的原始数据进行筛选,所以通常都是只有 Mapper 阶段,这一点需要注意!
/**
* 进行 ETL 流程的 Mapper,不需要走 Reducer
*
* @author zc-cris
* @version 1.0
**/
@SuppressWarnings("JavaDoc")
public class MovieTopMapper extends Mapper<LongWritable, Text, Text, NullWritable> {
private Text k = new Text();
/** 通过工具类将每行数据进行校验和转换
* @param key 文本偏移量
* @param value 每行文本
* @param context MapReduce 上下文对象
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] strings = value.toString().split("\t");
String result = EtlStringUtil.handle(strings);
if (result != null) {
// 自定义数据清洗成功的计数器并自增
context.getCounter("ETLCounter", "true").increment(1);
k.set(result);
context.write(k, NullWritable.get());
} else {
// 自定义数据清洗失败并过滤的计数器并自增
context.getCounter("ETLCounter", "false").increment(1);
}
}
}
- EtlStringUtil
根据上面的 Mapper 阶段代码,可以发现我们需要一个工具类来完成具体的数据校验和转换,代码如下:
/**
* ETL 工具类
*
* @author zc-cris
* @version 1.0
**/
public class EtlStringUtil {
private static StringBuilder stringBuilder = new StringBuilder();
private static final int STANDARD_LENGTH = 9;
private static final int STANDARD_LENGTH_SUB_1 = 8;
/**
* 使用 main 方法做测试,保证工具类的可用性
*
* @param args main 方法的参数
*/
public static void main(String[] args) {
String handle = EtlStringUtil.handle("SDNkMu8ZT68\tw00dy911\t630\tPeople & Blogs\t186\t10181\t3.49\t494\tcris\tloveu\tsimida".split("\t"));
System.out.println("handle = " + handle);
}
/**
* 将输入的字符串数组转换为合格的数据
*
* @param strings 待处理的字符串数组
* @return 处理后的字符串
*/
static String handle(String[] strings) {
// 一定要清除原 StringBuilder 对象的字符串内容!!!
stringBuilder.delete(0, stringBuilder.length());
if (strings.length < STANDARD_LENGTH) {
return null;