茄子快传数据分析之原理分析及数据清洗

标签: hive

需求:联想集团有一款app产品叫茄子快传(有上亿的活跃用户,集中在第三世界国家)
现在需要开发一个数据分析系统,来对app的用户行为数据做各类分析;

原理:
流程如下图:
这里写图片描述
流程简单介绍:
用户通过茄子的客户端产生数据,
将使用时间,手机号,ip地址,手机的***,app的版本,app的下载渠道等重要信息上传到联想的web日志服务器上,服务器的后台系统打印出日志文件,通过flume(一种日志采集工具)将生成的日志上传到hdfs上,先进行数据清洗,将版本,渠道,用户等重要信息丢失的过滤掉,生成新的文件,数据加载到hive中,进行运算处理,处理后的结果通过sqoop(一种数据迁移工具)保存到关系型数据库中,比如MySql,再通过web服务器,将分析出的结果显示到浏览器上。
预处理需求(mapreduce):
1/ 请对app事件请求日志进行预处理:
a) 过滤掉一些不合法数据(缺失device_id,app_ver_name,os_name,app_token,city,release_channel字段需要过滤)
b) 将原格式json,解析成csv(逗号分隔的文本)格式,并去掉”events”字段
c) 在原始数据中,追加一个字段user_id(如果是苹果,就用device_id,如果是android,就用android_id)
数据预处理的时候,只需要map就可以完成,所以就不需要reduce了。
处理要求:device_id,app_ver_name,os_name,app_token,city,release_channel 缺失则过滤
代码如下

package com.cleanLog;

import java.io.IOException;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;


public class AppLogClean {


    public static class MapTask extends Mapper<LongWritable, Text, Text, NullWritable>{
        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, NullWritable>.Context context)
                throws IOException, InterruptedException {
            String line = value.toString();
            ObjectMapper mapper = new ObjectMapper();
            JsonNode log = mapper.readTree(line);
            JsonNode header = log.get("header");

            if(StringUtils.isBlank(header.get("device_id").getTextValue())||
                    //也可以直接getString()
                    StringUtils.isBlank(header.get("app_ver_name").getTextValue())||
                    StringUtils.isBlank(header.get("os_name").getTextValue())||
                    StringUtils.isBlank(header.get("app_token").getTextValue())||
                    StringUtils.isBlank(header.get("city").getTextValue())||
                    StringUtils.isBlank(header.get("release_channel").getTextValue())) {
                return;
            }else {
                String user_id = "";
                if (header.get("device_id_type").getTextValue().equals("mac")) {
                    user_id = header.get("device_id").getTextValue();
                } else {
                    user_id = header.get("android_id").getTextValue();
                }

                StringBuilder sb = new StringBuilder();
                sb.append(header.get("cid_sn").getTextValue()).append(",");
                sb.append(header.get("mobile_data_type").getTextValue()).append(",");
                sb.append(header.get("os_ver").getTextValue()).append(",");
                sb.append(header.get("mac").getTextValue()).append(",");
                sb.append(header.get("resolution").getTextValue()).append(",");
                sb.append(header.get("commit_time").getTextValue()).append(",");
                sb.append(header.get("sdk_ver").getTextValue()).append(",");
                sb.append(header.get("device_id_type").getTextValue()).append(",");
                sb.append(header.get("city").getTextValue()).append(",");
                sb.append(header.get("android_id").getTextValue()).append(",");
                sb.append(header.get("device_model").getTextValue()).append(",");
                sb.append(header.get("carrier").getTextValue()).append(",");
                sb.append(header.get("promotion_channel").getTextValue()).append(",");
                sb.append(header.get("app_ver_name").getTextValue()).append(",");
                sb.append(header.get("imei").getTextValue()).append(",");
                sb.append(header.get("app_ver_code").getTextValue()).append(",");
                sb.append(header.get("pid").getTextValue()).append(",");
                sb.append(header.get("net_type").getTextValue()).append(",");
                sb.append(header.get("device_id").getTextValue()).append(",");
                sb.append(header.get("app_device_id").getTextValue()).append(",");
                sb.append(header.get("release_channel").getTextValue()).append(",");
                sb.append(header.get("country").getTextValue()).append(",");
                sb.append(header.get("time_zone").getTextValue()).append(",");
                sb.append(header.get("os_name").getTextValue()).append(",");
                sb.append(header.get("manufacture").getTextValue()).append(",");
                sb.append(header.get("commit_id").getTextValue()).append(",");
                sb.append(header.get("app_token").getTextValue()).append(",");
                sb.append(header.get("account").getTextValue()).append(",");
                sb.append(header.get("app_id").getTextValue()).append(",");
                sb.append(header.get("build_num").getTextValue()).append(",");
                sb.append(header.get("language").getTextValue()).append(",");
                sb.append(user_id);

                context.write(new Text(sb.toString()), NullWritable.get());
            }

        }


        public static void main(String[] args) throws Exception {
            Configuration conf = new Configuration();
            Job job = Job.getInstance(conf);
            job.setJarByClass(AppLogClean.class);
            job.setMapperClass(MapTask.class);
            job.setOutputKeyClass(Text.class);

            //设置reduce的数量为0
            job.setNumReduceTasks(0);

            FileInputFormat.addInputPath(job, new Path("D:\\data\\appuserdata\\input\\20170102"));//这里可以设置成参数args[0]
            FileOutputFormat.setOutputPath(job, new Path("D:\\data\\appuserdata\\output\\20170102"));

            boolean completion = job.waitForCompletion(true);//提交的时候也可以是submit,只不过这个是能看到过程。

            System.out.println(completion?"成功":"失败");

        }
    }
}

这样,数据就简单的清理了,只需要将生成的文件再放到集群上就可以用hive进行处理了。

版权声明:本文为wlk_328909605原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wlk_328909605/article/details/82227410

智能推荐

小程序日历选择插件源码

公司需要用到小程序日历段时间选择模块,找了好多都不太靠谱,最终参考别人思考自己需求,开发了这个源码,提供大家使用! 主要代码: 下载地址:https://download.csdn.net/download/huangsiqing88/11128276...

取消Android Studio本地项目关联SVN

作者:谭东 SVN现在大部分快要被Git替代了,所以也应该有很多人想把SVN的项目更改提交到Git上面。那么这就涉及到把原项目取消SVN关联。 现在给大家讲解Android Studio取消关联的方法。 1、项目找到.idea下的vsc.xml,把里面的vcs="svn"里的svn去掉,变为vcs=""即可。 2、删除对应项目文件夹里的各层的.svn文件夹及...

【Network Security!】信息的扫描与嗅探

文章目录 确定扫描目标 确定目标主机IP地址 网站架构探测 确定扫描目标 确定目标主机IP地址 1.获取本机IP地址 2.获取网站地址信息 3.获取指定网站的IP地址 4.确定可能开放的端口和服务 Zenmap是一款非常流行的端口扫描软件(nmap的GUI界面化)。它是用Python语言编写而成的开源的图形界面,能够运行在不同操作系统平台上(Windows/Linux/Unix/Mac OS)) ...

太赞了!Linux 架构师总结的学习笔记,提供下载

  本文字数:1247,阅读时长大约:1分钟 导读:你想学习 Linux 吗? 最近很多小伙伴找我要一些 Linux 基础资料,于是我翻箱倒柜,把这份技术大牛总结的 Linux 归纳笔记找出来,免费共享给大家! 据说有小伙伴靠这份笔记顺利进入 BAT 哦,所以一定要好好学习这份资料! 资料介绍 这份资料非常全面且详细,从 Linux 常用命令到 Linux 常用操作,再到shell编程、...

【底层原理】高级开发必须懂的"字节对齐"

认识字节对齐之前,假定int(4Byte),char(1Byte),short(2Byte) 认识字节对齐 先看段代码:   sizeof(Data1)和sizeof(Data2)分别表示Data1和Data2内存占用字节数,输出结果不一样是因为编译时对Data1和Data2做了不同的字节对齐。Data1的对齐为4Byte,Data2的对齐是2Byte。   假定存储起始地址为...

猜你喜欢

爬lol全英雄皮肤

初学爬虫简单的爬取一下lol全英雄皮肤,自己写的,和网上CV的好不一样,觉得文章说得过去的记得留下足迹。 一 分析页面 1.英雄列表 首先在英雄页面找到hero_list.js;至于为什么是这个文件,看图: 观察该文件响应头,获取访问的url,打开新的窗口,访问该链接,能获取对应数据。(这边显示在一行很男查看,推荐一款好用的chrome插件JSONView,可以帮帮我们格式化json数据,可以在g...

解决VUE项目重复点击菜单报错:Avoided redundant navigation to current location: “/xxxxx“. 问题

描述: 报错见下图: 解决方法: 在router文件夹下添加下面一段代码...

Nginx 入门指南(十)

负载均衡模块 负载均衡模块用于从upstream指令定义的后端主机列表中选取一台主机。Nginx 先使用负载均衡模块找到一台主机,再使用 upstream 模块实现与这台主机的交互。为了方便介绍负载均衡模块,做到言之有物,以下选取 Nginx 内置的 ip hash 模块作为实际例子进行分析。 配置 要了解负载均衡模块的开发方法,首先需要了解负载均衡模块的使用方法。因为负载均衡模块与之前书中提到的...

文本和输入:复制和粘贴

Android提供了一个功能强大的基于剪贴板的复制和粘贴框架。 它支持简单和复杂的数据类型,包括文本字符串,复杂数据结构,文本和二进制流数据,甚至应用程序资产。 简单的文本数据直接存储在剪贴板中,而复杂数据则作为粘贴应用程序与内容提供者解析的参考进行存储。 复制和粘贴在应用程序中以及在实现框架的应用程序之间工作。 由于框架的一部分使用内容提供者,因此本主题假定您熟悉Android内容提供程序API...

[unity]代码批量修改图片、文本文件的AssetBundle的Name

  当项目工程内有大量文件,需要打包成AssetBundle的时候,一个一个打包是一件非常麻烦的事情。 批量修改AssetBundle的Name并对AssetBundle包 进行批量 打包。   批量修改项目工程文件的图片、文本文件的AssetBundle   1.批量建立AssetBundle 1.1修改文件的.meta文件的文本内容 来自参考资料1   ...