这个项目是流量经营项目,通过Hadoop的离线数据项目。

运营商通过HTTP日志,分析用户的上网行为数据,进行行为轨迹的增强。

HTTP数据格式为:

流程:

系统架构:

技术选型:

这里只针对其中的一个功能进行说明:

其中规则库是人工填充的,实例库是采用机器学习自动生成的,形式都是<url,info>。

(一)统计流量排名前80%的URL,只有少数的URL流量比特别高,绝大多数的URL流量极低,没有参考价值,应当舍弃。

FlowBean.java:

  1. package cn.itcast.hadoop.mr.flowsum;
  2.  
  3. import java.io.DataInput;
  4. import java.io.DataOutput;
  5. import java.io.IOException;
  6.  
  7. import org.apache.hadoop.io.Writable;
  8. import org.apache.hadoop.io.WritableComparable;
  9.  
  10. public class FlowBean implements WritableComparable<FlowBean>{
  11.  
  12. private String phoneNB;
  13. private long up_flow;
  14. private long d_flow;
  15. private long s_flow;
  16.  
  17. //在反序列化时,反射机制需要调用空参构造函数,所以显示定义了一个空参构造函数
  18. public FlowBean(){}
  19.  
  20. //为了对象数据的初始化方便,加入一个带参的构造函数
  21. public FlowBean(String phoneNB, long up_flow, long d_flow) {
  22. this.phoneNB = phoneNB;
  23. this.up_flow = up_flow;
  24. this.d_flow = d_flow;
  25. this.s_flow = up_flow + d_flow;
  26. }
  27.  
  28. public void set(String phoneNB, long up_flow, long d_flow) {
  29. this.phoneNB = phoneNB;
  30. this.up_flow = up_flow;
  31. this.d_flow = d_flow;
  32. this.s_flow = up_flow + d_flow;
  33. }
  34.  
  35. public String getPhoneNB() {
  36. return phoneNB;
  37. }
  38.  
  39. public void setPhoneNB(String phoneNB) {
  40. this.phoneNB = phoneNB;
  41. }
  42.  
  43. public long getUp_flow() {
  44. return up_flow;
  45. }
  46.  
  47. public void setUp_flow(long up_flow) {
  48. this.up_flow = up_flow;
  49. }
  50.  
  51. public long getD_flow() {
  52. return d_flow;
  53. }
  54.  
  55. public void setD_flow(long d_flow) {
  56. this.d_flow = d_flow;
  57. }
  58.  
  59. public long getS_flow() {
  60. return s_flow;
  61. }
  62.  
  63. public void setS_flow(long s_flow) {
  64. this.s_flow = s_flow;
  65. }
  66.  
  67. //将对象数据序列化到流中
  68. @Override
  69. public void write(DataOutput out) throws IOException {
  70.  
  71. out.writeUTF(phoneNB);
  72. out.writeLong(up_flow);
  73. out.writeLong(d_flow);
  74. out.writeLong(s_flow);
  75.  
  76. }
  77.  
  78. //从数据流中反序列出对象的数据
  79. //从数据流中读出对象字段时,必须跟序列化时的顺序保持一致
  80. @Override
  81. public void readFields(DataInput in) throws IOException {
  82.  
  83. phoneNB = in.readUTF();
  84. up_flow = in.readLong();
  85. d_flow = in.readLong();
  86. s_flow = in.readLong();
  87.  
  88. }
  89.  
  90. @Override
  91. public String toString() {
  92.  
  93. return "" + up_flow + "\t" +d_flow + "\t" + s_flow;
  94. }
  95.  
  96. @Override
  97. public int compareTo(FlowBean o) {
  98. return s_flow>o.getS_flow()?-1:1;
  99. }
  100.  
  101. }

TopkURLMapper.java:

  1. package cn.itcast.hadoop.mr.llyy.topkurl;
  2.  
  3. import java.io.IOException;
  4.  
  5. import org.apache.commons.lang.StringUtils;
  6. import org.apache.hadoop.io.LongWritable;
  7. import org.apache.hadoop.io.Text;
  8. import org.apache.hadoop.mapreduce.Mapper;
  9.  
  10. import cn.itcast.hadoop.mr.flowsum.FlowBean;
  11.  
  12. public class TopkURLMapper extends Mapper<LongWritable, Text, Text, FlowBean> {
  13.  
  14. private FlowBean bean = new FlowBean();
  15. private Text k = new Text();
  16.  
  17. @Override
  18. protected void map(LongWritable key, Text value, Context context)
  19. throws IOException, InterruptedException {
  20.  
  21. String line = value.toString();
  22.  
  23. String[] fields = StringUtils.split(line, "\t");
  24. try {
  25. if (fields.length > 32 && StringUtils.isNotEmpty(fields[26])
  26. && fields[26].startsWith("http")) {
  27. String url = fields[26];
  28.  
  29. long up_flow = Long.parseLong(fields[30]);
  30. long d_flow = Long.parseLong(fields[31]);
  31.  
  32. k.set(url);
  33. bean.set("", up_flow, d_flow);
  34.  
  35. context.write(k, bean);
  36. }
  37. } catch (Exception e) {
  38.  
  39. System.out.println();
  40.  
  41. }
  42. }
  43.  
  44. }

TopkURLReducer.java:

  1. package cn.itcast.hadoop.mr.llyy.topkurl;
  2.  
  3. import java.io.IOException;
  4. import java.util.Map.Entry;
  5. import java.util.Set;
  6. import java.util.TreeMap;
  7.  
  8. import org.apache.hadoop.hdfs.server.namenode.HostFileManager.EntrySet;
  9. import org.apache.hadoop.io.LongWritable;
  10. import org.apache.hadoop.io.Text;
  11. import org.apache.hadoop.mapreduce.Reducer;
  12.  
  13. import cn.itcast.hadoop.mr.flowsum.FlowBean;
  14.  
  15. public class TopkURLReducer extends Reducer<Text, FlowBean, Text, LongWritable>{
  16. private TreeMap<FlowBean,Text> treeMap = new TreeMap<>();
  17. private double globalCount = 0;
  18.  
  19. // <url,{bean,bean,bean,.......}>
  20. @Override
  21. protected void reduce(Text key, Iterable<FlowBean> values,Context context)
  22. throws IOException, InterruptedException {
  23. Text url = new Text(key.toString());
  24. long up_sum = 0;
  25. long d_sum = 0;
  26. for(FlowBean bean : values){
  27.  
  28. up_sum += bean.getUp_flow();
  29. d_sum += bean.getD_flow();
  30. }
  31.  
  32. FlowBean bean = new FlowBean("", up_sum, d_sum);
  33. //每求得一条url的总流量,就累加到全局流量计数器中,等所有的记录处理完成后,globalCount中的值就是全局的流量总和
  34. globalCount += bean.getS_flow();
  35. treeMap.put(bean,url);
  36.  
  37. }
  38.  
  39. //cleanup方法是在reduer任务即将退出时被调用一次
  40. @Override
  41. protected void cleanup(Context context)
  42. throws IOException, InterruptedException {
  43.  
  44. Set<Entry<FlowBean, Text>> entrySet = treeMap.entrySet();
  45. double tempCount = 0;
  46.  
  47. for(Entry<FlowBean, Text> ent: entrySet){
  48.  
  49. if(tempCount / globalCount < 0.8){
  50.  
  51. context.write(ent.getValue(), new LongWritable(ent.getKey().getS_flow()));
  52. tempCount += ent.getKey().getS_flow();
  53.  
  54. }else{
  55. return;
  56. }
  57.  
  58. }
  59.  
  60. }
  61.  
  62. }

TopkURLRunner.java:

  1. package cn.itcast.hadoop.mr.llyy.topkurl;
  2.  
  3. import org.apache.hadoop.conf.Configuration;
  4. import org.apache.hadoop.conf.Configured;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.io.LongWritable;
  7. import org.apache.hadoop.io.Text;
  8. import org.apache.hadoop.mapreduce.Job;
  9. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  10. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  11. import org.apache.hadoop.util.Tool;
  12. import org.apache.hadoop.util.ToolRunner;
  13.  
  14. import cn.itcast.hadoop.mr.flowsum.FlowBean;
  15.  
  16. public class TopkURLRunner extends Configured implements Tool{
  17.  
  18. @Override
  19. public int run(String[] args) throws Exception {
  20.  
  21. Configuration conf = new Configuration();
  22. Job job = Job.getInstance(conf);
  23.  
  24. job.setJarByClass(TopkURLRunner.class);
  25.  
  26. job.setMapperClass(TopkURLMapper.class);
  27. job.setReducerClass(TopkURLReducer.class);
  28.  
  29. job.setMapOutputKeyClass(Text.class);
  30. job.setMapOutputValueClass(FlowBean.class);
  31.  
  32. job.setOutputKeyClass(Text.class);
  33. job.setOutputValueClass(LongWritable.class);
  34.  
  35. FileInputFormat.setInputPaths(job, new Path(args[0]));
  36. FileOutputFormat.setOutputPath(job, new Path(args[1]));
  37.  
  38. return job.waitForCompletion(true)?0:1;
  39. }
  40.  
  41. public static void main(String[] args) throws Exception {
  42. int res = ToolRunner.run(new Configuration(), new TopkURLRunner(), args);
  43. System.exit(res);
  44.  
  45. }
  46.  
  47. }

(二)将统计的URL导入到数据库中,这是URL规则库,一共就两个字段,URL和info说明,info是人工来实现,贴上标签。

将上面的运行结果通过sqoop导入到数据库中,然后通过数据库读取再跑mapreduce程序。

DBLoader.java:数据库的工具类。

  1. package cn.itcast.hadoop.mr.llyy.enhance;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.Statement;
  6. import java.util.HashMap;
  7.  
  8. public class DBLoader {
  9.  
  10. public static void dbLoader(HashMap<String, String> ruleMap) {
  11.  
  12. Connection conn = null;
  13. Statement st = null;
  14. ResultSet res = null;
  15.  
  16. try {
  17. Class.forName("com.mysql.jdbc.Driver");
  18. conn = DriverManager.getConnection("jdbc:mysql://weekend01:3306/urlcontentanalyse", "root", "root");
  19. st = conn.createStatement();
  20. res = st.executeQuery("select url,info from urlrule");
  21. while (res.next()) {
  22. ruleMap.put(res.getString(1), res.getString(2));
  23. }
  24.  
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27.  
  28. } finally {
  29. try{
  30. if(res!=null){
  31. res.close();
  32. }
  33. if(st!=null){
  34. st.close();
  35. }
  36. if(conn!=null){
  37. conn.close();
  38. }
  39.  
  40. }catch(Exception e){
  41. e.printStackTrace();
  42. }
  43. }
  44.  
  45. }
  46.  
  47. public static void main(String[] args) {
  48. DBLoader db = new DBLoader();
  49. HashMap<String, String> map = new HashMap<String,String>();
  50. db.dbLoader(map);
  51. System.out.println(map.size());
  52. }
  53.  
  54. }

LogEnhanceOutputFormat.java:默认是TextOutputFormat,这里我需要实现将不同的结果输到不同的文件中,而不是_SUCCESS中,所以我需要重写一个format。

  1. package cn.itcast.hadoop.mr.llyy.enhance;
  2.  
  3. import java.io.IOException;
  4.  
  5. import org.apache.hadoop.conf.Configuration;
  6. import org.apache.hadoop.fs.FSDataOutputStream;
  7. import org.apache.hadoop.fs.FileSystem;
  8. import org.apache.hadoop.fs.Path;
  9. import org.apache.hadoop.mapreduce.RecordWriter;
  10. import org.apache.hadoop.mapreduce.TaskAttemptContext;
  11. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  12.  
  13. public class LogEnhanceOutputFormat<K, V> extends FileOutputFormat<K, V> {
  14.  
  15. @Override
  16. public RecordWriter<K, V> getRecordWriter(TaskAttemptContext job)
  17. throws IOException, InterruptedException {
  18.  
  19. FileSystem fs = FileSystem.get(new Configuration());
  20. FSDataOutputStream enhancedOs = fs.create(new Path("/liuliang/output/enhancedLog"));
  21. FSDataOutputStream tocrawlOs = fs.create(new Path("/liuliang/output/tocrawl"));
  22.  
  23. return new LogEnhanceRecordWriter<K, V>(enhancedOs,tocrawlOs);
  24. }
  25.  
  26. public static class LogEnhanceRecordWriter<K, V> extends RecordWriter<K, V>{
  27. private FSDataOutputStream enhancedOs =null;
  28. private FSDataOutputStream tocrawlOs =null;
  29.  
  30. public LogEnhanceRecordWriter(FSDataOutputStream enhancedOs,FSDataOutputStream tocrawlOs){
  31.  
  32. this.enhancedOs = enhancedOs;
  33. this.tocrawlOs = tocrawlOs;
  34.  
  35. }
  36.  
  37. @Override
  38. public void write(K key, V value) throws IOException,
  39. InterruptedException {
  40.  
  41. if(key.toString().contains("tocrawl")){
  42. tocrawlOs.write(key.toString().getBytes());
  43. }else{
  44. enhancedOs.write(key.toString().getBytes());
  45. }
  46.  
  47. }
  48.  
  49. @Override
  50. public void close(TaskAttemptContext context) throws IOException,
  51. InterruptedException {
  52.  
  53. if(enhancedOs != null){
  54. enhancedOs.close();
  55. }
  56. if(tocrawlOs != null){
  57. tocrawlOs.close();
  58. }
  59.  
  60. }
  61.  
  62. }
  63.  
  64. }

然后再从所有原始日志中抽取URL,查询规则库,如果由info标签,则追加在原始日志后面。否则,这个URL就是带爬取URL,后面追加tocrawl,这两种不同情况要输出到不同文件中。

LogEnhanceMapper.java:

  1. package cn.itcast.hadoop.mr.llyy.enhance;
  2.  
  3. import java.io.IOException;
  4. import java.util.HashMap;
  5.  
  6. import org.apache.commons.lang.StringUtils;
  7. import org.apache.hadoop.io.LongWritable;
  8. import org.apache.hadoop.io.NullWritable;
  9. import org.apache.hadoop.io.Text;
  10. import org.apache.hadoop.mapreduce.Mapper;
  11.  
  12. /**
  13. *
  14. *
  15. * 读入原始日志数据,抽取其中的url,查询规则库,获得该url指向的网页内容的分析结果,追加到原始日志后
  16. *
  17. * @author duanhaitao@itcast.cn
  18. *
  19. */
  20.  
  21. // 读入原始数据 (47个字段) 时间戳 ..... destip srcip ... url .. . get 200 ...
  22. // 抽取其中的url查询规则库得到众多的内容识别信息 网站类别,频道类别,主题词,关键词,影片名,主演,导演。。。。
  23. // 将分析结果追加到原始日志后面
  24. // context.write( 时间戳 ..... destip srcip ... url .. . get 200 ...
  25. // 网站类别,频道类别,主题词,关键词,影片名,主演,导演。。。。)
  26. // 如果某条url在规则库中查不到结果,则输出到带爬清单
  27. // context.write( url tocrawl)
  28. public class LogEnhanceMapper extends
  29. Mapper<LongWritable, Text, Text, NullWritable> {
  30.  
  31. private HashMap<String, String> ruleMap = new HashMap<>();
  32.  
  33. // setup方法是在mapper task 初始化时被调用一次
  34. @Override
  35. protected void setup(Context context) throws IOException,
  36. InterruptedException {
  37. DBLoader.dbLoader(ruleMap);
  38. }
  39.  
  40. @Override
  41. protected void map(LongWritable key, Text value, Context context)
  42. throws IOException, InterruptedException {
  43.  
  44. String line = value.toString();
  45.  
  46. String[] fields = StringUtils.split(line, "\t");
  47. try {
  48. if (fields.length > 27 && StringUtils.isNotEmpty(fields[26])
  49. && fields[26].startsWith("http")) {
  50. String url = fields[26];
  51. String info = ruleMap.get(url);
  52. String result = "";
  53. if (info != null) {
  54. result = line + "\t" + info + "\n\r";
  55. context.write(new Text(result), NullWritable.get());
  56. } else {
  57. result = url + "\t" + "tocrawl" + "\n\r";
  58. context.write(new Text(result), NullWritable.get());
  59. }
  60.  
  61. } else {
  62. return;
  63. }
  64. } catch (Exception e) {
  65. System.out.println("exception occured in mapper.....");
  66. }
  67. }
  68.  
  69. }

LogEnhanceRunner.java:

  1. package cn.itcast.hadoop.mr.llyy.enhance;
  2.  
  3. import org.apache.hadoop.conf.Configuration;
  4. import org.apache.hadoop.conf.Configured;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.io.NullWritable;
  7. import org.apache.hadoop.io.Text;
  8. import org.apache.hadoop.mapreduce.Job;
  9. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  10. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  11. import org.apache.hadoop.util.Tool;
  12. import org.apache.hadoop.util.ToolRunner;
  13.  
  14. public class LogEnhanceRunner extends Configured implements Tool{
  15.  
  16. @Override
  17. public int run(String[] args) throws Exception {
  18.  
  19. Configuration conf = new Configuration();
  20.  
  21. Job job = Job.getInstance(conf);
  22.  
  23. job.setJarByClass(LogEnhanceRunner.class);
  24.  
  25. job.setMapperClass(LogEnhanceMapper.class);
  26.  
  27. job.setOutputKeyClass(Text.class);
  28. job.setOutputValueClass(NullWritable.class);
  29.  
  30. job.setOutputFormatClass(LogEnhanceOutputFormat.class);
  31.  
  32. FileInputFormat.setInputPaths(job, new Path(args[0]));
  33. FileOutputFormat.setOutputPath(job, new Path(args[1]));
  34.  
  35. return job.waitForCompletion(true)?0:1;
  36. }
  37.  
  38. public static void main(String[] args) throws Exception {
  39. int res = ToolRunner.run(new Configuration(), new LogEnhanceRunner(),args);
  40. System.exit(res);
  41. }
  42.  
  43. }

这里不写reduce也行。

MapReduce实现Top K问题:https://blog.csdn.net/u011750989/article/details/11482805?locationNum=5

Hadoop项目实战的更多相关文章

  1. Hadoop项目实战-用户行为分析之应用概述(三)

    1.概述 本课程的视频教程地址:<项目工程准备> 本节给大家分享的主题如下图所示: 下面我开始为大家分享今天的第三节的内容——<项目工程准备>,接下来开始分享今天的内容. 2. ...

  2. Hadoop项目实战-用户行为分析之应用概述(二)

    1.概述 本课程的视频教程地址:<项目整体概述> 本节给大家分享的主题如下图所示: 下面我开始为大家分享第二节的内容——<项目整体概述>,下面开始今天的分享内容. 2.内容 从 ...

  3. Hadoop项目实战-用户行为分析之应用概述(一)

    1.概述 本课程的视频教程地址:<Hadoop 回顾> 好的,下面就开始本篇教程的内容分享,本篇教程我为大家介绍我们要做一个什么样的Hadoop项目,并且对Hadoop项目的基本特点和其中 ...

  4. Hadoop项目实战-用户行为分析之编码实践

    1.概述 本课程的视频教程地址:<用户行为分析之编码实践> 本课程以用户行为分析案例为基础,带着大家去完成对各个KPI的编码工作,以及应用调度工作,让大家通过本课程掌握Hadoop项目的编 ...

  5. Hadoop项目实战-用户行为分析之分析与设计

    1.概述 本课程的视频教程地址:<用户行为分析之分析与设计> 下面开始本教程的学习,本教程以用户行为分析案例为基础,带着大家对项目的各个指标做详细的分析,对项目的整体设计做合理的规划,让大 ...

  6. hadoop项目实战--ETL--(二)实现自动向mysql中添加数据

    四 项目开发 1 创建数据库db_etl,新建两张表user 和oder.表结构如第一部分图所示. 2 编写python脚本,实现自动向mysql中插入数据. 新建python 项目,目录结构如下图 ...

  7. hadoop项目实战--ETL--(一)项目分析

    项目描述 一 项目简介 在远程服务器上的数据库中有两张表,user 和order,现需要对表中的数据做分析,将分析后的结果再存到mysql中.两张表的结构如下图所示 现需要分析每一天user和,ode ...

  8. hadoop项目实战--ETL--(三)实现mysql表到HIVE表的全量导入与增量导入

    一 在HIVE中创建ETL数据库 ->create database etl; 二 在工程目录下新建MysqlToHive.py 和conf文件夹 在conf文件夹下新建如下文件,最后的工程目录 ...

  9. 深入浅出Hadoop Mahout数据挖掘实战(算法分析、项目实战、中文分词技术)

    Mahout简介 Mahout 是 Apache Software Foundation(ASF) 旗下的一个开源项目, 提供一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建 ...

随机推荐

  1. C# 调用 Web Service 时出现 : 407 Proxy Authentication Required错误的解决办法

    // 记得 using System.Net; System.Net.WebProxy myProxy = new System.Net.WebProxy("localhost:9099&q ...

  2. Android-自己定义PopupWindow

    Android-自己定义PopupWindow 2014年5月12日 PopupWindow在应用中应该是随处可见的,非经常常使用到,比方在旧版本号的微信其中就用到下拉的PopupWindow.那是自 ...

  3. Android,TextView的所有属性和方法

    XML 属性 属性名称 相关方法 描述 android:autoLink setAutoLinkMask(int) 设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接. ...

  4. 树莓派学习笔记——GPIO功能学习

    0.前言     树莓派现在越来越火,网上树莓派的资料也越来越多.树莓派的学习可以分为linux系统学习和linux驱动学习,利用树莓派制作LED流水灯应该算是驱动学习吧.树莓派来自国外,国外嵌入式开 ...

  5. Hibernate关系映射(三) 多对一和一对多

    一.多对一 学生Student和班级Grade实现多对一,多个学生对应一个班级. Student.java实体类,映射了班级的属性. package com.lxit.entity; import j ...

  6. IntelliJ IDEA 学习(四)Idea逆向生成数据库实体类

    第一步配置 数据库 第二步  配置hibernate,如果没有cfg.xml文件,点击ok后会自动生成 第三步 选择hibernate配置文件生成实体 第四步 设置完点击,选中要生成的实体的表 注意: ...

  7. Linux相关面试题&答案

    Linux相关面试题&答案 Linux面试题&答案 假设apache日志格式为:118.78.199.98 – - [09/Jan/2010:00:59:59 +0800] " ...

  8. Unity3D系列教程--使用免费工具在Unity3D中开发2D游戏 第一节

    声明:   本博客文章翻译类别的均为个人翻译,版权全部.出处: http://blog.csdn.net/ml3947,个人博客:http://www.wjfxgame.com. 译者说明:这是一个系 ...

  9. HTML-HTML5+CSS3权威指南阅读(三、CSS选择器)

    1.伪元素选择器 first-line, first-letter, before, after 2.属性选择器 [attr*=val]: 如果元素的 attr 属性中包含用 val 指定的字符的话, ...

  10. 解决异常断电导致的: CorruptSSTableException: java.io.EOFException

    问题产生 服务器重启,导致cassandra损坏,整个集群不可用.所使用的cassandra为2.1.9版本. 问题描述 运行启动命令,报错如下: DEBUG :: All segments have ...