Hadoop项目实战
这个项目是流量经营项目,通过Hadoop的离线数据项目。
运营商通过HTTP日志,分析用户的上网行为数据,进行行为轨迹的增强。
HTTP数据格式为:
流程:
系统架构:
技术选型:
这里只针对其中的一个功能进行说明:
其中规则库是人工填充的,实例库是采用机器学习自动生成的,形式都是<url,info>。
(一)统计流量排名前80%的URL,只有少数的URL流量比特别高,绝大多数的URL流量极低,没有参考价值,应当舍弃。
FlowBean.java:
- package cn.itcast.hadoop.mr.flowsum;
- import java.io.DataInput;
- import java.io.DataOutput;
- import java.io.IOException;
- import org.apache.hadoop.io.Writable;
- import org.apache.hadoop.io.WritableComparable;
- public class FlowBean implements WritableComparable<FlowBean>{
- private String phoneNB;
- private long up_flow;
- private long d_flow;
- private long s_flow;
- //在反序列化时,反射机制需要调用空参构造函数,所以显示定义了一个空参构造函数
- public FlowBean(){}
- //为了对象数据的初始化方便,加入一个带参的构造函数
- public FlowBean(String phoneNB, long up_flow, long d_flow) {
- this.phoneNB = phoneNB;
- this.up_flow = up_flow;
- this.d_flow = d_flow;
- this.s_flow = up_flow + d_flow;
- }
- public void set(String phoneNB, long up_flow, long d_flow) {
- this.phoneNB = phoneNB;
- this.up_flow = up_flow;
- this.d_flow = d_flow;
- this.s_flow = up_flow + d_flow;
- }
- public String getPhoneNB() {
- return phoneNB;
- }
- public void setPhoneNB(String phoneNB) {
- this.phoneNB = phoneNB;
- }
- public long getUp_flow() {
- return up_flow;
- }
- public void setUp_flow(long up_flow) {
- this.up_flow = up_flow;
- }
- public long getD_flow() {
- return d_flow;
- }
- public void setD_flow(long d_flow) {
- this.d_flow = d_flow;
- }
- public long getS_flow() {
- return s_flow;
- }
- public void setS_flow(long s_flow) {
- this.s_flow = s_flow;
- }
- //将对象数据序列化到流中
- @Override
- public void write(DataOutput out) throws IOException {
- out.writeUTF(phoneNB);
- out.writeLong(up_flow);
- out.writeLong(d_flow);
- out.writeLong(s_flow);
- }
- //从数据流中反序列出对象的数据
- //从数据流中读出对象字段时,必须跟序列化时的顺序保持一致
- @Override
- public void readFields(DataInput in) throws IOException {
- phoneNB = in.readUTF();
- up_flow = in.readLong();
- d_flow = in.readLong();
- s_flow = in.readLong();
- }
- @Override
- public String toString() {
- return "" + up_flow + "\t" +d_flow + "\t" + s_flow;
- }
- @Override
- public int compareTo(FlowBean o) {
- return s_flow>o.getS_flow()?-1:1;
- }
- }
TopkURLMapper.java:
- package cn.itcast.hadoop.mr.llyy.topkurl;
- import java.io.IOException;
- import org.apache.commons.lang.StringUtils;
- import org.apache.hadoop.io.LongWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Mapper;
- import cn.itcast.hadoop.mr.flowsum.FlowBean;
- public class TopkURLMapper extends Mapper<LongWritable, Text, Text, FlowBean> {
- private FlowBean bean = new FlowBean();
- private Text k = new Text();
- @Override
- protected void map(LongWritable key, Text value, Context context)
- throws IOException, InterruptedException {
- String line = value.toString();
- String[] fields = StringUtils.split(line, "\t");
- try {
- if (fields.length > 32 && StringUtils.isNotEmpty(fields[26])
- && fields[26].startsWith("http")) {
- String url = fields[26];
- long up_flow = Long.parseLong(fields[30]);
- long d_flow = Long.parseLong(fields[31]);
- k.set(url);
- bean.set("", up_flow, d_flow);
- context.write(k, bean);
- }
- } catch (Exception e) {
- System.out.println();
- }
- }
- }
TopkURLReducer.java:
- package cn.itcast.hadoop.mr.llyy.topkurl;
- import java.io.IOException;
- import java.util.Map.Entry;
- import java.util.Set;
- import java.util.TreeMap;
- import org.apache.hadoop.hdfs.server.namenode.HostFileManager.EntrySet;
- import org.apache.hadoop.io.LongWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Reducer;
- import cn.itcast.hadoop.mr.flowsum.FlowBean;
- public class TopkURLReducer extends Reducer<Text, FlowBean, Text, LongWritable>{
- private TreeMap<FlowBean,Text> treeMap = new TreeMap<>();
- private double globalCount = 0;
- // <url,{bean,bean,bean,.......}>
- @Override
- protected void reduce(Text key, Iterable<FlowBean> values,Context context)
- throws IOException, InterruptedException {
- Text url = new Text(key.toString());
- long up_sum = 0;
- long d_sum = 0;
- for(FlowBean bean : values){
- up_sum += bean.getUp_flow();
- d_sum += bean.getD_flow();
- }
- FlowBean bean = new FlowBean("", up_sum, d_sum);
- //每求得一条url的总流量,就累加到全局流量计数器中,等所有的记录处理完成后,globalCount中的值就是全局的流量总和
- globalCount += bean.getS_flow();
- treeMap.put(bean,url);
- }
- //cleanup方法是在reduer任务即将退出时被调用一次
- @Override
- protected void cleanup(Context context)
- throws IOException, InterruptedException {
- Set<Entry<FlowBean, Text>> entrySet = treeMap.entrySet();
- double tempCount = 0;
- for(Entry<FlowBean, Text> ent: entrySet){
- if(tempCount / globalCount < 0.8){
- context.write(ent.getValue(), new LongWritable(ent.getKey().getS_flow()));
- tempCount += ent.getKey().getS_flow();
- }else{
- return;
- }
- }
- }
- }
TopkURLRunner.java:
- package cn.itcast.hadoop.mr.llyy.topkurl;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.conf.Configured;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.io.LongWritable;
- 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;
- import cn.itcast.hadoop.mr.flowsum.FlowBean;
- public class TopkURLRunner extends Configured implements Tool{
- @Override
- public int run(String[] args) throws Exception {
- Configuration conf = new Configuration();
- Job job = Job.getInstance(conf);
- job.setJarByClass(TopkURLRunner.class);
- job.setMapperClass(TopkURLMapper.class);
- job.setReducerClass(TopkURLReducer.class);
- job.setMapOutputKeyClass(Text.class);
- job.setMapOutputValueClass(FlowBean.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(LongWritable.class);
- FileInputFormat.setInputPaths(job, new Path(args[0]));
- FileOutputFormat.setOutputPath(job, new Path(args[1]));
- return job.waitForCompletion(true)?0:1;
- }
- public static void main(String[] args) throws Exception {
- int res = ToolRunner.run(new Configuration(), new TopkURLRunner(), args);
- System.exit(res);
- }
- }
(二)将统计的URL导入到数据库中,这是URL规则库,一共就两个字段,URL和info说明,info是人工来实现,贴上标签。
将上面的运行结果通过sqoop导入到数据库中,然后通过数据库读取再跑mapreduce程序。
DBLoader.java:数据库的工具类。
- package cn.itcast.hadoop.mr.llyy.enhance;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.Statement;
- import java.util.HashMap;
- public class DBLoader {
- public static void dbLoader(HashMap<String, String> ruleMap) {
- Connection conn = null;
- Statement st = null;
- ResultSet res = null;
- try {
- Class.forName("com.mysql.jdbc.Driver");
- conn = DriverManager.getConnection("jdbc:mysql://weekend01:3306/urlcontentanalyse", "root", "root");
- st = conn.createStatement();
- res = st.executeQuery("select url,info from urlrule");
- while (res.next()) {
- ruleMap.put(res.getString(1), res.getString(2));
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try{
- if(res!=null){
- res.close();
- }
- if(st!=null){
- st.close();
- }
- if(conn!=null){
- conn.close();
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- DBLoader db = new DBLoader();
- HashMap<String, String> map = new HashMap<String,String>();
- db.dbLoader(map);
- System.out.println(map.size());
- }
- }
LogEnhanceOutputFormat.java:默认是TextOutputFormat,这里我需要实现将不同的结果输到不同的文件中,而不是_SUCCESS中,所以我需要重写一个format。
- package cn.itcast.hadoop.mr.llyy.enhance;
- import java.io.IOException;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FSDataOutputStream;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.mapreduce.RecordWriter;
- import org.apache.hadoop.mapreduce.TaskAttemptContext;
- import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
- public class LogEnhanceOutputFormat<K, V> extends FileOutputFormat<K, V> {
- @Override
- public RecordWriter<K, V> getRecordWriter(TaskAttemptContext job)
- throws IOException, InterruptedException {
- FileSystem fs = FileSystem.get(new Configuration());
- FSDataOutputStream enhancedOs = fs.create(new Path("/liuliang/output/enhancedLog"));
- FSDataOutputStream tocrawlOs = fs.create(new Path("/liuliang/output/tocrawl"));
- return new LogEnhanceRecordWriter<K, V>(enhancedOs,tocrawlOs);
- }
- public static class LogEnhanceRecordWriter<K, V> extends RecordWriter<K, V>{
- private FSDataOutputStream enhancedOs =null;
- private FSDataOutputStream tocrawlOs =null;
- public LogEnhanceRecordWriter(FSDataOutputStream enhancedOs,FSDataOutputStream tocrawlOs){
- this.enhancedOs = enhancedOs;
- this.tocrawlOs = tocrawlOs;
- }
- @Override
- public void write(K key, V value) throws IOException,
- InterruptedException {
- if(key.toString().contains("tocrawl")){
- tocrawlOs.write(key.toString().getBytes());
- }else{
- enhancedOs.write(key.toString().getBytes());
- }
- }
- @Override
- public void close(TaskAttemptContext context) throws IOException,
- InterruptedException {
- if(enhancedOs != null){
- enhancedOs.close();
- }
- if(tocrawlOs != null){
- tocrawlOs.close();
- }
- }
- }
- }
然后再从所有原始日志中抽取URL,查询规则库,如果由info标签,则追加在原始日志后面。否则,这个URL就是带爬取URL,后面追加tocrawl,这两种不同情况要输出到不同文件中。
LogEnhanceMapper.java:
- package cn.itcast.hadoop.mr.llyy.enhance;
- import java.io.IOException;
- import java.util.HashMap;
- import org.apache.commons.lang.StringUtils;
- import org.apache.hadoop.io.LongWritable;
- import org.apache.hadoop.io.NullWritable;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Mapper;
- /**
- *
- *
- * 读入原始日志数据,抽取其中的url,查询规则库,获得该url指向的网页内容的分析结果,追加到原始日志后
- *
- * @author duanhaitao@itcast.cn
- *
- */
- // 读入原始数据 (47个字段) 时间戳 ..... destip srcip ... url .. . get 200 ...
- // 抽取其中的url查询规则库得到众多的内容识别信息 网站类别,频道类别,主题词,关键词,影片名,主演,导演。。。。
- // 将分析结果追加到原始日志后面
- // context.write( 时间戳 ..... destip srcip ... url .. . get 200 ...
- // 网站类别,频道类别,主题词,关键词,影片名,主演,导演。。。。)
- // 如果某条url在规则库中查不到结果,则输出到带爬清单
- // context.write( url tocrawl)
- public class LogEnhanceMapper extends
- Mapper<LongWritable, Text, Text, NullWritable> {
- private HashMap<String, String> ruleMap = new HashMap<>();
- // setup方法是在mapper task 初始化时被调用一次
- @Override
- protected void setup(Context context) throws IOException,
- InterruptedException {
- DBLoader.dbLoader(ruleMap);
- }
- @Override
- protected void map(LongWritable key, Text value, Context context)
- throws IOException, InterruptedException {
- String line = value.toString();
- String[] fields = StringUtils.split(line, "\t");
- try {
- if (fields.length > 27 && StringUtils.isNotEmpty(fields[26])
- && fields[26].startsWith("http")) {
- String url = fields[26];
- String info = ruleMap.get(url);
- String result = "";
- if (info != null) {
- result = line + "\t" + info + "\n\r";
- context.write(new Text(result), NullWritable.get());
- } else {
- result = url + "\t" + "tocrawl" + "\n\r";
- context.write(new Text(result), NullWritable.get());
- }
- } else {
- return;
- }
- } catch (Exception e) {
- System.out.println("exception occured in mapper.....");
- }
- }
- }
LogEnhanceRunner.java:
- package cn.itcast.hadoop.mr.llyy.enhance;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.conf.Configured;
- 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 LogEnhanceRunner extends Configured implements Tool{
- @Override
- public int run(String[] args) throws Exception {
- Configuration conf = new Configuration();
- Job job = Job.getInstance(conf);
- job.setJarByClass(LogEnhanceRunner.class);
- job.setMapperClass(LogEnhanceMapper.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(NullWritable.class);
- job.setOutputFormatClass(LogEnhanceOutputFormat.class);
- FileInputFormat.setInputPaths(job, new Path(args[0]));
- FileOutputFormat.setOutputPath(job, new Path(args[1]));
- return job.waitForCompletion(true)?0:1;
- }
- public static void main(String[] args) throws Exception {
- int res = ToolRunner.run(new Configuration(), new LogEnhanceRunner(),args);
- System.exit(res);
- }
- }
这里不写reduce也行。
MapReduce实现Top K问题:https://blog.csdn.net/u011750989/article/details/11482805?locationNum=5
Hadoop项目实战的更多相关文章
- Hadoop项目实战-用户行为分析之应用概述(三)
1.概述 本课程的视频教程地址:<项目工程准备> 本节给大家分享的主题如下图所示: 下面我开始为大家分享今天的第三节的内容——<项目工程准备>,接下来开始分享今天的内容. 2. ...
- Hadoop项目实战-用户行为分析之应用概述(二)
1.概述 本课程的视频教程地址:<项目整体概述> 本节给大家分享的主题如下图所示: 下面我开始为大家分享第二节的内容——<项目整体概述>,下面开始今天的分享内容. 2.内容 从 ...
- Hadoop项目实战-用户行为分析之应用概述(一)
1.概述 本课程的视频教程地址:<Hadoop 回顾> 好的,下面就开始本篇教程的内容分享,本篇教程我为大家介绍我们要做一个什么样的Hadoop项目,并且对Hadoop项目的基本特点和其中 ...
- Hadoop项目实战-用户行为分析之编码实践
1.概述 本课程的视频教程地址:<用户行为分析之编码实践> 本课程以用户行为分析案例为基础,带着大家去完成对各个KPI的编码工作,以及应用调度工作,让大家通过本课程掌握Hadoop项目的编 ...
- Hadoop项目实战-用户行为分析之分析与设计
1.概述 本课程的视频教程地址:<用户行为分析之分析与设计> 下面开始本教程的学习,本教程以用户行为分析案例为基础,带着大家对项目的各个指标做详细的分析,对项目的整体设计做合理的规划,让大 ...
- hadoop项目实战--ETL--(二)实现自动向mysql中添加数据
四 项目开发 1 创建数据库db_etl,新建两张表user 和oder.表结构如第一部分图所示. 2 编写python脚本,实现自动向mysql中插入数据. 新建python 项目,目录结构如下图 ...
- hadoop项目实战--ETL--(一)项目分析
项目描述 一 项目简介 在远程服务器上的数据库中有两张表,user 和order,现需要对表中的数据做分析,将分析后的结果再存到mysql中.两张表的结构如下图所示 现需要分析每一天user和,ode ...
- hadoop项目实战--ETL--(三)实现mysql表到HIVE表的全量导入与增量导入
一 在HIVE中创建ETL数据库 ->create database etl; 二 在工程目录下新建MysqlToHive.py 和conf文件夹 在conf文件夹下新建如下文件,最后的工程目录 ...
- 深入浅出Hadoop Mahout数据挖掘实战(算法分析、项目实战、中文分词技术)
Mahout简介 Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目, 提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建 ...
随机推荐
- C# 调用 Web Service 时出现 : 407 Proxy Authentication Required错误的解决办法
// 记得 using System.Net; System.Net.WebProxy myProxy = new System.Net.WebProxy("localhost:9099&q ...
- Android-自己定义PopupWindow
Android-自己定义PopupWindow 2014年5月12日 PopupWindow在应用中应该是随处可见的,非经常常使用到,比方在旧版本号的微信其中就用到下拉的PopupWindow.那是自 ...
- Android,TextView的所有属性和方法
XML 属性 属性名称 相关方法 描述 android:autoLink setAutoLinkMask(int) 设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接. ...
- 树莓派学习笔记——GPIO功能学习
0.前言 树莓派现在越来越火,网上树莓派的资料也越来越多.树莓派的学习可以分为linux系统学习和linux驱动学习,利用树莓派制作LED流水灯应该算是驱动学习吧.树莓派来自国外,国外嵌入式开 ...
- Hibernate关系映射(三) 多对一和一对多
一.多对一 学生Student和班级Grade实现多对一,多个学生对应一个班级. Student.java实体类,映射了班级的属性. package com.lxit.entity; import j ...
- IntelliJ IDEA 学习(四)Idea逆向生成数据库实体类
第一步配置 数据库 第二步 配置hibernate,如果没有cfg.xml文件,点击ok后会自动生成 第三步 选择hibernate配置文件生成实体 第四步 设置完点击,选中要生成的实体的表 注意: ...
- Linux相关面试题&答案
Linux相关面试题&答案 Linux面试题&答案 假设apache日志格式为:118.78.199.98 – - [09/Jan/2010:00:59:59 +0800] " ...
- Unity3D系列教程--使用免费工具在Unity3D中开发2D游戏 第一节
声明: 本博客文章翻译类别的均为个人翻译,版权全部.出处: http://blog.csdn.net/ml3947,个人博客:http://www.wjfxgame.com. 译者说明:这是一个系 ...
- HTML-HTML5+CSS3权威指南阅读(三、CSS选择器)
1.伪元素选择器 first-line, first-letter, before, after 2.属性选择器 [attr*=val]: 如果元素的 attr 属性中包含用 val 指定的字符的话, ...
- 解决异常断电导致的: CorruptSSTableException: java.io.EOFException
问题产生 服务器重启,导致cassandra损坏,整个集群不可用.所使用的cassandra为2.1.9版本. 问题描述 运行启动命令,报错如下: DEBUG :: All segments have ...