Hive实战之视频网站数据分析
需求描述:
统计影音视频网站的常规指标,各种TopN指标:
- 统计视频观看数Top10
- 统计视频类别热度Top10
- 统计视频观看数Top20所属类别以及类别包含的Top20的视频个数
- 统计视频观看数Top50所关联视频的所属类别Rank
- 统计每个类别中的视频热度Top10
- 统计每个类别中视频流量Top10
- 统计上传视频最多的用户Top10以及他们上传的观看次数在前20视频
- 统计每个类别视频观看数Top10
项目
数据表构成
- 视频表
字段 | 备注 | 详细描述 |
---|---|---|
video id | 视频唯一id | 11位字符串 |
uploader | 视频上传者 | 上传视频的用户名String |
age | 视频年龄 | 视频在平台上的整数天 |
category | 视频类别 | 上传视频指定的视频分类 |
length | 视频长度 | 整形数字标识的视频长度 |
views | 观看次数 | 视频被浏览的次数 |
rate | 视频评分 | 满分5分 |
ratings | 流量 | 视频的流量,整型数字 |
conments | 评论数 | 一个视频的整数评论数 |
related ids | 相关视频id | 相关视频的id,最多20个 |
- 用户表
字段 | 备注 | 字段类型 |
---|---|---|
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
思路:
即统计每个类别有多少个视频,显示出包含视频最多的前10个类别。
需要按照类别group by聚合,然后count组内的videoId个数即可。
因为当前表结构为:一个视频对应一个或多个类别。所以如果要group by类别,需要先将类别进行列转行(展开),然后再进行count即可。
最后按照热度排序,显示前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视频的个数
思路:
先找到观看数最高的20个视频所属条目的所有信息,降序排列
把这20条信息中的category分裂出来(列转行)
最后查询视频分类名称和该分类下有多少个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
思路:
- 查询出观看数最多的前50个视频的所有信息(当然包含了每个视频对应的关联视频),记为临时表t1
t1:观看数前50的视频
select *
from video_orc
order by views
desc limit 50;
- 将找到的50条视频信息的相关视频relatedId列转行,记为临时表t2
t2:将相关视频的id进行列转行操作
select explode(relatedId) as videoId
from t1;
- 将相关视频的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;
- 按照视频类别进行分组,统计每组视频个数,然后排行
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为例
思路:
要想统计Music类别中的视频热度Top10,需要先找到Music类别,那么就需要将category展开,所以可以创建一张表用于存放categoryId展开的数据。
向category展开的表中插入数据。
统计对应类别(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为例
思路:
创建视频类别展开表(categoryId列转行后的表)
按照ratings排序即可
select videoId,views,ratings
from video_category
where categoryId = "Music"
order by ratings
desc limit 10;
统计上传视频最多的用户Top10以及他们上传的观看次数在前20的视频
思路:
- 先找到上传视频最多的10个用户的用户信息
select *
from video_user_orc
order by videos
desc limit 10;
- 通过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
思路:
先得到categoryId展开的表数据
子查询按照categoryId进行分区,然后分区内排序,并生成递增数字,该递增数字这一列起名为rank列
通过子查询产生的临时表,查询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实战之视频网站数据分析相关推荐
- python视频网站项目_Python超羽量级灵活框架 Flask实战微电影视频网站 大小项目通吃 Flask实战项目...
课程名称: Python超羽量级灵活框架 Flask实战微电影视频网站 大小项目通吃 Flask实战项目视频教程 课程简介: Flask作为Python编写的Web小型框架,可以使用Python快速开 ...
- go语言mysql视频_Go语言实战流媒体视频网站
第1章 课程介绍 介绍这门课程大纲,技术堆栈以及环境 1-1 prestudy 1-2 课程介绍及知识要点预习 第2章 一个例子了解golang工具链 通过一个简单的webservice具体从gola ...
- Go语言实战流媒体视频网站_调试和修改bug
我将最后修改好的放在了3xxx上了,见下面第一个地址. https://github.com/3xxx/golang-streaming 代码来自: https://github.com/alanho ...
- 流媒体视频网站Go语言实现
项目开源地址 Github:https://github.com/JIeJaitt/stmsrv API 设计 List all videos:URL:user/ 总结一下 api 根据 Handle ...
- HDFS与Hive实战 + 滴滴出行数据分析
HDFS与Hive实战 + 滴滴出行数据分析 1.HDFS 1.1 分布式文件系统 1.2 HDFS的Shell命令行 1.3 启动Hadoop集群 1.4 大数据环境清单 2.数据仓库 2.1 数据 ...
- python爬虫实战-爬取视频网站下载视频至本地(selenium)
#python爬虫实战-爬取视频网站下载视频至本地(selenium) import requests from lxml import etree import json from selenium ...
- 基于股票大数据分析的Python入门实战(视频教学版)的插图汇总
在我写的这本书,<基于股票大数据分析的Python入门实战(视频教学版)>里,用能吸引人的股票案例,带领大家入门Python的语法,数据分析和机器学习. 京东链接是这个:https://i ...
- Hive(三、0)案例之视频网站指标
Hive(三.0)案例之视频网站常规指标@你宝爷 一.前期准备 1.0.打开集群&服务&客户端 #1)注释掉配置文件内容,这样就不用开启metastore服务啦vim $HIVE_HO ...
- 【数据分析】Python :视频网站数据清洗整理和结论研究
视频网站数据清洗整理和结论研究 要求: 1.数据清洗 - 去除空值 要求:创建函数 提示:fillna方法填充缺失数据,注意inplace参数 2.数据清洗 - 时间标签转化 要求: ① 将时间字段改 ...
- 网站数据分析思路讲解
网站数据分析思路讲解,网站数据分析基本是围绕顾客进行.不同的人.部门.目标不同对网站数据分析的要求也不同.对网站进行数据分析的前提是需要明确数据分析的目标是什么,主要用来做什么. 举个几个例子:管理层 ...
最新文章
- Python Qt GUI设计:QClipboard剪贴数据类(基础篇—19)
- 白盒测试之语句分支条件覆盖
- CXF框架实现webservice实例
- 马哥运维架构 第一周作业
- 基于deep learning的快速图像检索系统
- java 多目录 编译jar_javac编译多个包下的、依赖其他jar包的java文件
- RHEL 6.5 中的KVM虚拟化新特性
- 跨境电商将成全球贸易的主角,下半年跨境电商趋势是什么?
- python写爬虫4-多线程爬虫(采集58出租房信息)_python实现多线程爬虫
- 杨国勋:云计算颠覆现有市场和产业格局
- windows java路径问题_java 文件路径问题
- 地大计算机学院保研华科人数,2020年华中科技大学保研率是多少
- 由条件熵与无条件熵的关系引出的不等式证明题(不会抄答案系列)
- t-SNE数据降维可视化
- Windchill 零件操作通用类
- linux敏感内容检测工具,认识Linux平台四大IDS***检测工具
- 数据中心网络架构 — 网络带宽的收敛比
- 费曼算法(Feynman algorithm)
- linux 串口 数量限制,linux – 你的Unix的TTY主要数量是多少?
- 登录mysql时遇到了:mysql: [Warning] Using a password on the command line interface can be insecure.
热门文章
- 什么是敏捷项目管理?
- 小米/红米手机刷第三方rom(红米5 plus为例)
- android微信连wifi设置,微信小程序实现连接wifi功能的方法
- 好的计算机书籍 http://outmyth.blogdriver.com/outmyth/1122212.html
- 《Visual Basic.Net 循序渐进》阅读器说明
- Angular 数据循环
- RK3399 hi3559A 平台离线语音识别、合成、翻译、声纹
- FPGA芯片供电总结
- 三菱Q系列PLC项目资料 本系统采用三菱Q系列PLC,本系统中用到16个伺服电机,采用16轴控制器通过光纤驱动16个伺服
- C#编程基础(初级)(五)——函数,结构函数,委托