需求描述:

统计影音视频网站的常规指标,各种TopN指标:

  • 统计视频观看数Top10
  • 统计视频类别热度Top10
  • 统计视频观看数Top20所属类别以及类别包含的Top20的视频个数
  • 统计视频观看数Top50所关联视频的所属类别Rank
  • 统计每个类别中的视频热度Top10
  • 统计每个类别中视频流量Top10
  • 统计上传视频最多的用户Top10以及他们上传的观看次数在前20视频
  • 统计每个类别视频观看数Top10

项目

数据表构成

  1. 视频表
字段 备注 详细描述
video id 视频唯一id 11位字符串
uploader 视频上传者 上传视频的用户名String
age 视频年龄 视频在平台上的整数天
category 视频类别 上传视频指定的视频分类
length 视频长度 整形数字标识的视频长度
views 观看次数 视频被浏览的次数
rate 视频评分 满分5分
ratings 流量 视频的流量,整型数字
conments 评论数 一个视频的整数评论数
related ids 相关视频id 相关视频的id,最多20个
  1. 用户表
字段 备注 字段类型
uploader 上传者用户名 string
videos 上传视频数 int
friends 朋友数量 int

源数据ETL

通过观察原始数据形式,可以发现,视频可以有多个所属分类,每个所属分类用&符号分割,且分割的两边有空格字符,同时相关视频也是可以有多个元素,多个相关视频又用“\t”进行分割。为了分析数据时方便对存在多个子元素的数据进行操作,首先进行数据重组清洗操作。即:将所有的类别用“&”分割,同时去掉两边空格,多个相关视频id也使用“&”进行分割。

ETLUtil.java工具类

public class ETLUtil {public static String oriString2ETLString(String ori){StringBuilder etlString = new StringBuilder();String[] splits = ori.split("\t");if(splits.length < 9) return null;splits[3] = splits[3].replace(" ", "");for(int i = 0; i < splits.length; i++){if(i < 9){if(i == splits.length - 1){etlString.append(splits[i]);                  }else{etlString.append(splits[i] + "\t");    }}else{if(i == splits.length - 1){etlString.append(splits[i]);}else{etlString.append(splits[i] + "&");}}}return etlString.toString();}
}

VideoETLMapper.java

import java.io.IOException;import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;import com.src.util.ETLUtil;public class VideoETLMapper extends Mapper<Object, Text, NullWritable, Text>{Text text = new Text();@Overrideprotected void map(Object key, Text value, Context context) throws IOException, InterruptedException {String etlString = ETLUtil.oriString2ETLString(value.toString());if(StringUtils.isBlank(etlString)) return;text.set(etlString);context.write(NullWritable.get(), text);}
}

ETLRunner.java

import java.io.IOException;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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 VideoETLRunner implements Tool {private Configuration conf = null;@Overridepublic void setConf(Configuration conf) {this.conf = conf;}@Overridepublic Configuration getConf() {return this.conf;}@Overridepublic int run(String[] args) throws Exception {conf = this.getConf();conf.set("inpath", args[0]);conf.set("outpath", args[1]);Job job = Job.getInstance(conf);job.setJarByClass(VideoETLRunner.class);job.setMapperClass(VideoETLMapper.class);job.setMapOutputKeyClass(NullWritable.class);job.setMapOutputValueClass(Text.class);job.setNumReduceTasks(0);this.initJobInputPath(job);this.initJobOutputPath(job);return job.waitForCompletion(true) ? 0 : 1;}private void initJobOutputPath(Job job) throws IOException {Configuration conf = job.getConfiguration();String outPathString = conf.get("outpath");FileSystem fs = FileSystem.get(conf);Path outPath = new Path(outPathString);if(fs.exists(outPath)){fs.delete(outPath, true);}FileOutputFormat.setOutputPath(job, outPath);}private void initJobInputPath(Job job) throws IOException {Configuration conf = job.getConfiguration();String inPathString = conf.get("inpath");FileSystem fs = FileSystem.get(conf);Path inPath = new Path(inPathString);if(fs.exists(inPath)){FileInputFormat.addInputPath(job, inPath);}else{throw new RuntimeException("HDFS中该文件目录不存在:" + inPathString);}}public static void main(String[] args) {try {int resultCode = ToolRunner.run(new VideoETLRunner(), args);if(resultCode == 0){System.out.println("Success!");}else{System.out.println("Fail!");}System.exit(resultCode);} catch (Exception e) {e.printStackTrace();System.exit(1);}}
}

将数据打包,执行ETL操作

bin/yarn jar ~/softwares/jars/ETL-0.0.1-SNAPSHOT.jar  com.src.etl.ETLVideosRunner
/keven/video/2008/0222  /keven/output/video/2008/0222

创建表

创建表(原始表):

  • video_ori
create table video_ori(videoId string, uploader string, age int, category array<string>, length int, views int, rate float, ratings int, comments int,relatedId array<string>)
row format delimited
fields terminated by "\t"
collection items terminated by "&"
stored as textfile;
  • video_user_ori
create table video_user_ori(uploader string,videos int,friends int)
row format delimited
fields terminated by "\t"
stored as textfile;

把原始数据插入到orc表中

  • video_orc
create table video_orc(videoId string, uploader string, age int, category array<string>, length int, views int, rate float, ratings int, comments int,relatedId array<string>)
row format delimited fields terminated by "\t"
collection items terminated by "&"
stored as orc;
  • video_user_orc
create table video_user_orc(uploader string,videos int,friends int)
row format delimited
fields terminated by "\t"
stored as orc;

导入ETL数据

  • video_ori:
load data inpath "/video/output/video/2008/0222" into  table video_ori;
  • video_user_ori:
 load data inpath "/video/user/2008/0903" into table  video_user_ori;

ORC表插入数据

  • video_orc:
 insert into table video_orc select * from video_ori;
  • video_user_orc:

    insert into table video_user_orc select * from video_user_ori;
    

业务分析

统计视频观看数Top10

思路:使用order by按照views字段做一个全局排序即可,同时我们设置只显示前10条。

select videoId, uploader, age, category, length, views, rate, ratings, comments
from video_orc
order by views
desc limit 10;

统计视频类别热度Top10

思路:

  1. 即统计每个类别有多少个视频,显示出包含视频最多的前10个类别。

  2. 需要按照类别group by聚合,然后count组内的videoId个数即可。

  3. 因为当前表结构为:一个视频对应一个或多个类别。所以如果要group by类别,需要先将类别进行列转行(展开),然后再进行count即可。

  4. 最后按照热度排序,显示前10条。

select category_name as category, count(t1.videoId) as hot
from (select videoId,category_name from video_orc lateral view explode(category) t_catetory as category_name) t1
group by t1.category_name
order by hot
desc limit 10;

统计出视频观看数最高的20个视频的所属类别以及类别包含Top20视频的个数

思路:

  1. 先找到观看数最高的20个视频所属条目的所有信息,降序排列

  2. 把这20条信息中的category分裂出来(列转行)

  3. 最后查询视频分类名称和该分类下有多少个Top20的视频

select category_name as category, count(t2.videoId) as hot_with_views
from (select videoId, category_name from (select * from video_orc order by views desc limit 20) t1 lateral view explode(category) t_catetory as category_name) t2
group by category_name
order by hot_with_views
desc;

统计视频观看数Top50所关联视频的所属类别Rank

思路:

  1. 查询出观看数最多的前50个视频的所有信息(当然包含了每个视频对应的关联视频),记为临时表t1

t1:观看数前50的视频

select *
from video_orc
order by views
desc limit 50;
  1. 将找到的50条视频信息的相关视频relatedId列转行,记为临时表t2

t2:将相关视频的id进行列转行操作

select explode(relatedId) as videoId
from t1;
  1. 将相关视频的id和video_orc表进行inner join操作

t5:得到两列数据,一列是category,一列是之前查询出来的相关视频id

 (select distinct(t2.videoId), t3.category
from t2
inner join video_orc t3 on t2.videoId = t3.videoId) t4 lateral view explode(category) t_catetory as category_name;
  1. 按照视频类别进行分组,统计每组视频个数,然后排行
select category_name as category, count(t5.videoId) as hot
from (select videoId, category_name from (select distinct(t2.videoId), t3.category from (select explode(relatedId) as videoId from (select * from video_orc order by views desc limit 50) t1) t2 inner join video_orc t3 on t2.videoId = t3.videoId) t4 lateral view explode(category) t_catetory as category_name) t5
group by category_name
order by hot
desc;

统计每个类别中的视频热度Top10,以Music为例

思路:

  1. 要想统计Music类别中的视频热度Top10,需要先找到Music类别,那么就需要将category展开,所以可以创建一张表用于存放categoryId展开的数据。

  2. 向category展开的表中插入数据。

  3. 统计对应类别(Music)中的视频热度。

创建表类别表:

create table video_category(videoId string, uploader string, age int, categoryId string, length int, views int, rate float, ratings int, comments int, relatedId array<string>)
row format delimited
fields terminated by "\t"
collection items terminated by "&"
stored as orc;

向类别表中插入数据:

insert into table video_category  select videoId,uploader,age,categoryId,length,views,rate,ratings,comments,      relatedId from video_orc lateral view explode(category) catetory as categoryId;

统计Music类别的Top10(也可以统计其他)

select videoId, views
from video_category
where categoryId = "Music"
order by views
desc limit10;

统计每个类别中视频流量Top10,以Music为例

思路:

  1. 创建视频类别展开表(categoryId列转行后的表)

  2. 按照ratings排序即可

select videoId,views,ratings
from video_category
where categoryId = "Music"
order by ratings
desc limit 10;

统计上传视频最多的用户Top10以及他们上传的观看次数在前20的视频

思路:

  1. 先找到上传视频最多的10个用户的用户信息
select *
from video_user_orc
order by videos
desc limit 10;
  1. 通过uploader字段与video_orc表进行join,得到的信息按照views观看次数进行排序即可。
select t2.videoId, t2.views,t2.ratings,t1.videos,t1.friends
from (select  * from video_user_orc order by videos desc  limit  10) t1
join video_orc t2
on t1.uploader = t2.uploader
order by views desc
limit 20;

统计每个类别视频观看数Top10

思路:

  1. 先得到categoryId展开的表数据

  2. 子查询按照categoryId进行分区,然后分区内排序,并生成递增数字,该递增数字这一列起名为rank列

  3. 通过子查询产生的临时表,查询rank值小于等于10的数据行即可。

select t1.*
from (select videoId,categoryId,views,row_number() over(partition by categoryId order by views desc) rank from video_category) t1
where rank <= 10;

Hive实战之视频网站数据分析相关推荐

  1. python视频网站项目_Python超羽量级灵活框架 Flask实战微电影视频网站 大小项目通吃 Flask实战项目...

    课程名称: Python超羽量级灵活框架 Flask实战微电影视频网站 大小项目通吃 Flask实战项目视频教程 课程简介: Flask作为Python编写的Web小型框架,可以使用Python快速开 ...

  2. go语言mysql视频_Go语言实战流媒体视频网站

    第1章 课程介绍 介绍这门课程大纲,技术堆栈以及环境 1-1 prestudy 1-2 课程介绍及知识要点预习 第2章 一个例子了解golang工具链 通过一个简单的webservice具体从gola ...

  3. Go语言实战流媒体视频网站_调试和修改bug

    我将最后修改好的放在了3xxx上了,见下面第一个地址. https://github.com/3xxx/golang-streaming 代码来自: https://github.com/alanho ...

  4. 流媒体视频网站Go语言实现

    项目开源地址 Github:https://github.com/JIeJaitt/stmsrv API 设计 List all videos:URL:user/ 总结一下 api 根据 Handle ...

  5. HDFS与Hive实战 + 滴滴出行数据分析

    HDFS与Hive实战 + 滴滴出行数据分析 1.HDFS 1.1 分布式文件系统 1.2 HDFS的Shell命令行 1.3 启动Hadoop集群 1.4 大数据环境清单 2.数据仓库 2.1 数据 ...

  6. python爬虫实战-爬取视频网站下载视频至本地(selenium)

    #python爬虫实战-爬取视频网站下载视频至本地(selenium) import requests from lxml import etree import json from selenium ...

  7. 基于股票大数据分析的Python入门实战(视频教学版)的插图汇总

    在我写的这本书,<基于股票大数据分析的Python入门实战(视频教学版)>里,用能吸引人的股票案例,带领大家入门Python的语法,数据分析和机器学习. 京东链接是这个:https://i ...

  8. Hive(三、0)案例之视频网站指标

    Hive(三.0)案例之视频网站常规指标@你宝爷 一.前期准备 1.0.打开集群&服务&客户端 #1)注释掉配置文件内容,这样就不用开启metastore服务啦vim $HIVE_HO ...

  9. 【数据分析】Python :视频网站数据清洗整理和结论研究

    视频网站数据清洗整理和结论研究 要求: 1.数据清洗 - 去除空值 要求:创建函数 提示:fillna方法填充缺失数据,注意inplace参数 2.数据清洗 - 时间标签转化 要求: ① 将时间字段改 ...

  10. 网站数据分析思路讲解

    网站数据分析思路讲解,网站数据分析基本是围绕顾客进行.不同的人.部门.目标不同对网站数据分析的要求也不同.对网站进行数据分析的前提是需要明确数据分析的目标是什么,主要用来做什么. 举个几个例子:管理层 ...

最新文章

  1. Python Qt GUI设计:QClipboard剪贴数据类(基础篇—19)
  2. 白盒测试之语句分支条件覆盖
  3. CXF框架实现webservice实例
  4. 马哥运维架构 第一周作业
  5. 基于deep learning的快速图像检索系统
  6. java 多目录 编译jar_javac编译多个包下的、依赖其他jar包的java文件
  7. RHEL 6.5 中的KVM虚拟化新特性
  8. 跨境电商将成全球贸易的主角,下半年跨境电商趋势是什么?
  9. python写爬虫4-多线程爬虫(采集58出租房信息)_python实现多线程爬虫
  10. 杨国勋:云计算颠覆现有市场和产业格局
  11. windows java路径问题_java 文件路径问题
  12. 地大计算机学院保研华科人数,2020年华中科技大学保研率是多少
  13. 由条件熵与无条件熵的关系引出的不等式证明题(不会抄答案系列)
  14. t-SNE数据降维可视化
  15. Windchill 零件操作通用类
  16. linux敏感内容检测工具,认识Linux平台四大IDS***检测工具
  17. 数据中心网络架构 — 网络带宽的收敛比
  18. 费曼算法(Feynman algorithm)
  19. linux 串口 数量限制,linux – 你的Unix的TTY主要数量是多少?
  20. 登录mysql时遇到了:mysql: [Warning] Using a password on the command line interface can be insecure.

热门文章

  1. 什么是敏捷项目管理?
  2. 小米/红米手机刷第三方rom(红米5 plus为例)
  3. android微信连wifi设置,微信小程序实现连接wifi功能的方法
  4. 好的计算机书籍 http://outmyth.blogdriver.com/outmyth/1122212.html
  5. 《Visual Basic.Net 循序渐进》阅读器说明
  6. Angular 数据循环
  7. RK3399 hi3559A 平台离线语音识别、合成、翻译、声纹
  8. FPGA芯片供电总结
  9. 三菱Q系列PLC项目资料 本系统采用三菱Q系列PLC,本系统中用到16个伺服电机,采用16轴控制器通过光纤驱动16个伺服
  10. C#编程基础(初级)(五)——函数,结构函数,委托