大数据实战-callLog项目(通话记录数据分析)之数据分析

news/2024/11/8 17:34:39/

文章目录

  • 前言
  • mysql
    • 表结构设计
      • db_telecom.tb_contacts
      • db_telecom.tb_call
      • db_telecom.tb_dimension_date
    • 建表语句
    • 导入基础数据
      • 姓名手机号映射
      • 时间维度表
    • Meaven依赖
  • HBase
    • Maven依赖
    • mapper
    • reducer
    • 自定义输出
      • OutputFormat
      • MyRecordWriter
        • 私有属性
        • 初始化操作
    • 设置job
    • 运行
  • 博客链接

前言

有了之前存入HBase的数据,现在就可以运用HBase的MR进行数据分析了。

mysql

表结构设计

db_telecom.tb_contacts

用于存放用户手机号码与联系人姓名。

备注类型
id自增主键int(11) NOT NULL
telephone手机号码varchar(255) NOT NULL
name联系人姓名varchar(255) NOT NULL

db_telecom.tb_call

备注类型
iddatecontact 复合主键(联系人维度 id,时间维度 id) varchar(255) NOT NULL
iddatedimension 时间维度 id int(11) NOT NULL
idcontact查询人的电话号码 int(11) NOT NULL
callsum通话次数总和 int(11) NOT NULL DEFAULT 0
calldurationsum 通话时长总和 int(11)

db_telecom.tb_dimension_date

备注类型
id自增主键int(11)
year年,当前通话信息所在年int(11)
month月,当前通话信息所在月,如果按照年来统计信息,则month 为-1。int(11) NOT NULL
day日,当前通话信息所在日,如果是按照月来统计信息,则day为-1。int(11) NOT

建表语句

我这里简化了约束信息,自己建立的表,需要注意自己的默认字符集,不是utf8请选择下面的完整版,否则可能无法导入中文。

CREATE DATABASE db_telecom;CREATE TABLE tb_dimension_date(
id int PRIMARY KEY AUTO_INCREMENT,
year int,
month int,
day int);create table tb_contacts(
id int PRIMARY KEY AUTO_INCREMENT,
telephone char(11),
name varchar(20));CREATE TABLE tb_call( 
id_date_contact VARCHAR(10) PRIMARY KEY,
id_date_dimension int,
id_contact int, 
call_sum int, 
call_duration_sum int,
FOREIGN KEY(id_date_dimension) REFERENCES tb_dimension_date(id), 
FOREIGN KEY(id_contact) REFERENCES tb_contacts(id));  

下面是我老师提供的完整的建表语句

SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for tb_call
-- ----------------------------
DROP TABLE IF EXISTS `tb_call`;
CREATE TABLE `tb_call` (`id_date_contact` varchar(100) NOT NULL,`id_date_dimension` int(11) NOT NULL,`id_contact` int(11) NOT NULL,`call_sum` int(11) NOT NULL,`call_duration_sum` int(11) NOT NULL,PRIMARY KEY (`id_date_contact`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for tb_contacts
-- ----------------------------
DROP TABLE IF EXISTS `tb_contacts`;
CREATE TABLE `tb_contacts` (`id` int(11) NOT NULL AUTO_INCREMENT,`telephone` varchar(11) NOT NULL,`name` varchar(50) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for tb_dimension_date
-- ----------------------------
DROP TABLE IF EXISTS `tb_dimension_date`;
CREATE TABLE `tb_dimension_date` (`id` int(11) NOT NULL AUTO_INCREMENT,`year` int(11) NOT NULL,`month` int(11) NOT NULL,`day` int(11) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

导入基础数据

姓名手机号映射

我先修改了一下之前生成的文件,推荐用notepad++、或者sublime都有列编辑的工具,直接在每行开始添加",再进行局部替换。
在这里插入图片描述
可以直接在Navicat中导入csv文件
在这里插入图片描述
一直下一步到完成就行了,其中需要注意字段是否对应上
在这里插入图片描述
也可以用mysql命令
mysql --local-infile -uroot -proot db_telecom -e "LOAD DATA LOCAL INFILE 'nam_num.csv' INTO TABLE tb_contacts character set utf8 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'"

时间维度表

和上一步操作一样,这里不用担心字符集还简单一些
在这里插入图片描述

Meaven依赖

如果没有添加mysql驱动支持,需要添加上,之后才能用JDBC

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.20</version></dependency>

HBase

Maven依赖

检查是否有依赖,没有的话添加进去。

<dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>1.4.5</version></dependency><dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>1.4.5</version></dependency>

mapper

这时候也体现出了rowKey设计的好处,直接切分rowKey就能获得需要的数据

public static class HBase2MysqlMapper extends TableMapper<Text, IntWritable>{Text outKey = new Text();IntWritable outValue = new IntWritable();@Override//来一个,算三个维度protected void map(ImmutableBytesWritable key, Result value,Context context)throws IOException, InterruptedException {String rowKey = Bytes.toString(key.get());String[] strs = rowKey.split("_");//用于计算通话时长,只算一次即可if(strs[5].equals("01"))outValue.set(Integer.valueOf(strs[4]));elseoutValue.set(0);//日维度outKey.set(strs[1]+"_"+strs[2]);context.write(outKey, outValue);//月维度outKey.set(strs[1]+"_"+strs[2].substring(0, 7));context.write(outKey, outValue);//年维度outKey.set(strs[1]+"_"+strs[2].substring(0, 4));context.write(outKey, outValue);}}

reducer

和wordcount差不多,都是求和,key设计好就行了

public static class HBase2MysqlReducer extends Reducer<Text, IntWritable, Text, IntWritable>{Text outKey = new Text();IntWritable outValue = new IntWritable();int count,sum;@Overrideprotected void reduce(Text key, Iterable<IntWritable> values,Context context)throws IOException, InterruptedException {count = 0;sum = 0;for(IntWritable value:values){				//累计通话次数count += 1;//累计通话时长sum += value.get();}outKey.set(key.toString()+"_"+String.valueOf(count));outValue.set(sum);context.write(outKey, outValue);}}

自定义输出

这个需要自定义才能输出到Mysql比较麻烦

OutputFormat

不是输出到文件,不必继承FileOutputFormat,而是直接继承OutputFormat;核心是实现RecordWriter,另外两个方法可以参照FileOutputFormat,也可以直接return。

public class MySQLOutputFormat extends OutputFormat<Text, IntWritable>{@Overridepublic RecordWriter<Text, IntWritable> getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException {RecordWriter<Text, IntWritable> writer = new MyRecordWriter<Text, IntWritable>(job);return writer;}@Overridepublic void checkOutputSpecs(JobContext context) throws IOException, InterruptedException {return;		}@Overridepublic OutputCommitter getOutputCommitter(TaskAttemptContext context) throws IOException, InterruptedException {return new FileOutputCommitter(null, context);}}

MyRecordWriter

私有属性

	private Connection conn = null;private Statement stmt = null;

初始化操作

记得修改自己的url,还有密码

public MyRecordWriter(TaskAttemptContext context) {try {Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://node103:3306/db_telecom";String username = "root";String password = "root";conn = DriverManager.getConnection(url, username, password);stmt = conn.createStatement();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}

这是最关键的部分,就是查询出两个外键,然后构造成主键,插入mysql

	@Overridepublic void write(Text key, IntWritable value) throws IOException, InterruptedException {String[] strs = key.toString().split("_");Integer count = Integer.valueOf(strs[2]);String[] dimensions = strs[1].split("-");String year="-1",month="-1",day="-1";if(dimensions.length>2)day = dimensions[2];if(dimensions.length>1)month = dimensions[1];if(dimensions.length>0)year = dimensions[0];try {//获得手机号码对应的外键String querySql = "SELECT id FROM tb_contacts WHERE telephone = "+strs[0]+";";ResultSet rs = stmt.executeQuery(querySql);rs.next();String id_contact = rs.getString("id");//获得日期对应的外键querySql = "SELECT id FROM tb_dimension_date WHERE "+ "year = "+year+" AND month = "+month+" AND day = "+day+";";rs = stmt.executeQuery(querySql);rs.next();String id_date_dimension = rs.getString("id");//拼凑为主键String id_date_contact = id_date_dimension+"_"+id_contact;//插入String insertSql = "INSERT INTO tb_call "+"(id_date_contact,id_date_dimension,id_contact,"+ "call_sum,call_duration_sum) "+ "VALUES('"+id_date_contact+"',"+id_date_dimension+","+id_contact+","+count+","+value.get()+");";stmt.execute(insertSql);} catch (SQLException e) {e.printStackTrace();}}

设置job

我实现了Tool接口,主要在run中设置

public int run(String[] args) throws Exception {Job job = Job.getInstance(this.getConf());job.setJarByClass(HBase2MysqlDriver.class);TableMapReduceUtil.initTableMapperJob(args[0], new Scan(), HBase2MysqlMapper.class, Text.class, IntWritable.class, job);job.setReducerClass(HBase2MysqlReducer.class);job.setOutputFormatClass(MySQLOutputFormat.class);boolean result = job.waitForCompletion(true);return result?0:1;}

其他的代码就是走个形式了

	private Configuration conf;@Overridepublic void setConf(Configuration conf) {this.conf = conf;}@Overridepublic Configuration getConf() {return conf;}
public static void main(String[] args) {try {Configuration conf = HBaseConfiguration.create(); ToolRunner.run(conf, new HBase2MysqlDriver(), args);} catch (Exception e) {e.printStackTrace();}}

运行

直接在Eclipse中运行即可,数据库中的结果如下
在这里插入图片描述

博客链接

大数据实战-callLog项目(通话记录数据分析)之项目介绍
大数据实战-callLog项目(通话记录数据分析)之数据生产
大数据实战-callLog项目(通话记录数据分析)之数据采集
大数据实战-callLog项目(通话记录数据分析)之数据分析


http://www.ppmy.cn/news/853825.html

相关文章

Git 常见问题

Git 常见问题 Git 常见问题分支没有跟踪信息通常错误信息提示如下&#xff1a;解决方案 Git 常见问题 分支没有跟踪信息 如果在执行 git pull 时出现这个错误信息,通常是因为当前分支没有设置跟踪信息,Git不知道应该去哪个远程分支拉取代码。 通常错误信息提示如下&#xff…

javascript提取联通个人信息和通话记录的代码

由于一些巨大的困难&#xff0c;一些后端爬虫改成了前端爬虫。 前端爬虫是只有js语言&#xff0c;后端爬虫有python java nodejs php这些语言。 前端爬虫有window.document对象&#xff0c;在浏览器端的爬虫即使是二次发送ajax&#xff0c;也不需要学后端爬虫来构造一堆请求头&…

android通话记录手机号码归属地,mui 获取手机通话记录

export default { onLoad() { this.log(); // this.msg(); // this.concat(); }, methods: { log() { // 获取通话记录 plus.android.requestPermissions( [android.permission.READ_CALL_LOG, android.permission.WRITE_CALL_LOG, android.permission.READ_SMS], function(e) …

怎么看手机计算机的记录表,教您如何查看6个月前的通话记录,包括中国联通手机!...

如何查询6个月前的呼叫历史是Internet上的常见问题,因为无论是移动,联通还是电信,您都只能查询最近6个月的呼叫历史以及呼叫顺序6个月前的查询方法?答案是肯定的,因为无论是Apple手机还是Android手机,所有通话记录都保存在手机的文件中. 通过将其导出到计算机,我们可以直…

小程序主包超1.5MB分包处理流程优化方案

"subPackages": [// 分包1 {"root": "src, // 根目录"pages": [{"path": "views/business/index", // 页面路径"name": "business_index","aliasPath": "/business/index",&…

lotus lotus-miner version 1.23.2 boostd version 1.7.4

boost Web UI settings Libp2p Peer ID 查看ID 设置 Peer ID lotus-miner actor set-peer-id <Peer ID>发布矿工 lotus-miner actor set-addrs /ip4/公网IP/tcp/端口lotus 查询报价报错 lotus client query-ask <矿工> ERROR: bls signature failed to verify…

一个简单的网页制作期末作业,学生个人html静态网页制作成品代码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

再夺AI专业全球冠军!清华力压CMU夺得CSRankings高校AI领域第一

新智元报道 来源&#xff1a;CSRankings 每次CSRankings更新&#xff0c;都会引发舆论大哗。 今年这个让大家关注的排名终于又更新了&#xff01;全球院校计算机科学领域实力排名开源项目CSRankings&#xff0c;更新了2020-2021年的最新数据。 最新排名显示&#xff1a; AI&am…