1. 程式人生 > >搜狗日誌查詢分析 (MapReduce+Hive綜合實驗)

搜狗日誌查詢分析 (MapReduce+Hive綜合實驗)

前提條件:


安裝好hadoop2.7.3(Linux系統下)

安裝好MySQL(Windows系統下),推薦使用Xampp

安裝好Hive(Linux系統下)參考:Hive安裝配置

 
題目:

從搜狗實驗室下載搜尋資料進行分析

下載的資料包含6個欄位,資料格式說明如下:

訪問時間  使用者ID  [查詢詞]  該URL在返回結果中的排名  使用者點選的順序號  使用者點選的URL

注意:

1.欄位分隔符:欄位分隔符是個數不等的空格;

2.欄位個數:有些行有6個欄位,有些達不到6個欄位。

 

問題:使用MapReduce和Hive查詢出搜尋結果排名為第2名,點選順序排在第1的資料?

 


實驗步驟:
 

思路:用MapReduce做資料清洗,用Hive來分析資料。

1.下載資料來源

開啟搜狗實驗室連結
http://www.sogou.com/labs/resource/q.php

下載精簡版(一天資料,63MB)  tar.gz格式資料

下載後文件如下:

2.上傳下載檔案至HDFS

   2.1將下載的檔案通過WinScp工具上傳到Linux系統

  2.2 解壓SogouQ.reduced.tar.gz並上傳到HDFS

  解壓:

$ tar -zxvf SogouQ.reduced.tar.gz

可以用tail命令檢視解壓檔案最後3行的資料

tail -3 SogouQ.reduced

查詢詞為中文,這裡編碼按UTF-8查出來是亂碼,編碼時指定為‘GBK’可避免亂碼。資料格式如前面的說明:

訪問時間  使用者ID  [查詢詞]  該URL在返回結果中的排名  使用者點選的順序號  使用者點選的URL 

上傳至HDFS:

$ hdfs dfs -put SogouQ.reduced /

 

 

 

3.資料清洗

   因為原始資料中有些行的欄位數不為6,且原始資料的欄位分隔符不是Hive表規定的逗號',',所以需要對原始資料進行資料清洗。

  通過編寫MapReduce程式完成資料清洗:

      a.將不滿足6個欄位的行刪除

      b.將欄位分隔符由不等的空格變為逗號‘,’分隔符

3.1 Eclipse新建Maven工程:Zongheshiyan

Group Id填寫com, Artifact Id填寫Zongheshiyan

 

新建工程目錄結構如下: 

3.2 修改pom.xml檔案

 設定主類:在</project>一行之前新增如下語句

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <!-- main()所在的類,注意修改為包名+主類名 -->
                  <mainClass>com.Zongheshiyan.App</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

 新增依賴:在  </dependencies>一行之前新增如下語句

    <dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-common</artifactId>
	    <version>2.7.3</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-client</artifactId>
	    <version>2.7.3</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-hdfs</artifactId>
	    <version>2.7.3</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-mapreduce-client-core</artifactId>
	    <version>2.7.3</version>
    </dependency>

3.3 新建SogouMapper類

3.4 編寫程式碼

SogouMapper.java

package com.Zongheshiyan;


import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

//                                                                                         k1     ,        v1,     k2   ,    v2
public class SogouMapper extends Mapper<LongWritable,Text,Text,NullWritable> {

    @Override
    /**
     * 在任務開始時,被呼叫一次。且只會被呼叫一次。
     */
    protected void setup(Context context) throws IOException, InterruptedException {
        super.setup(context);
    }

    @Override
    protected void map(LongWritable k1, Text v1, Context context) throws IOException, InterruptedException {
        //避免亂碼
        //資料格式:20111230000005  57375476989eea12893c0c3811607bcf    奇藝高清        1      1      http://www.qiyi.com/
        String data = new String(v1.getBytes(),0,v1.getLength(),"GBK");
        
        //split("\\s+") \\s+為正則表示式,意思是匹配一個或多個空白字元,包括空格、製表、換頁符等。
        //參考:http://www.runoob.com/java/java-regular-expressions.html
        String words[] = data.split("\\s+");
        
        //判斷資料如果不等於6個欄位,則退出程式
        if(words.length != 6){
            return;//return語句後不帶返回值,作用是退出該程式的執行  https://www.cnblogs.com/paomoopt/p/3746963.html
        }
        //用逗號代替空白字元
        String newData = data.replaceAll("\\s+",",");
        //輸出
        context.write(new Text(newData),NullWritable.get());
    }

    @Override
    /**
     * 在任務結束時,被呼叫一次。且只會被呼叫一次。
     */
    protected void cleanup(Context context) throws IOException, InterruptedException {
        super.cleanup(context);
    }
}

 

 App.java

package com.Zongheshiyan;


import org.apache.hadoop.conf.Configuration;
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;


/**
 * 資料清洗器 主類
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception {
        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf);
        job.setJarByClass(App.class);

        //指定map輸出
        job.setMapperClass(SogouMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(NullWritable.class);

        //指定reduce的輸出
        job.setOutputKeyClass(Text.class);
        job.setMapOutputValueClass(NullWritable.class);

        //指定輸入、輸出
        FileInputFormat.setInputPaths(job,new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));

        //提交job,等待結束
        job.waitForCompletion(true);

    }
}

 3.5 打包工程:mvn clean package

 3.6上傳到Linux: WinScp工具

 3.7 執行jar包

  在執行jar包之前,確保開啟了hadoop所有程序

start-all.sh

 同時也把mr歷史伺服器程序開啟

mr-jobhistory-daemon.sh start historyserver

  執行jar包: 

hadoop jar Zongheshiyan-0.0.1-SNAPSHOT.jar /SogouQ.reduced /out/Oneday

機器配置不同,執行時間也不同(執行時間約3分鐘左右)。 看到輸出如下圖所示為執行成功。

 檢視輸出結果

hdfs dfs -ls /out/Oneday

檢視輸出檔案最後10行資料: 

hdfs dfs -tail /out/Oneday/part-r-00000

4.建立hive表

   進入hive命令列

hive

   建立hive表 

create table sogoulog_1(accesstime string,useID string,keyword string,no1 int,clickid int,url string) row format delimited fields terminated by ',';

 

5.將MapReduce清洗後的資料匯入Hive sogoulog_1表中

load data inpath '/out/Oneday/part-r-00000' into table sogoulog_1;

 

6.使用SQL查詢滿足條件的資料(只顯示前10條)

select * from sogoulog_1 where no1=2 and clickid=1 limit 10;

其實,還可以對資料做一些探索,例如:

檢視 sogoulog_1表結構

hive> describe sogoulog_1;

OK

accesstime           string                                   

useid                string                                   

keyword              string                                   

no1                  int                                      

clickid              int                                      

url                  string                                   

Time taken: 0.411 seconds, Fetched: 6 row(s)

一天內,一共搜尋關鍵詞的個數

hive> select count(keyword) from sogoulog_1;

1724253

第一次點選的次數來看,排名越靠前,點選次數越多

hive> select count(keyword) from sogoulog_1 where no1=1 and clickid=1;

279492

hive> select count(keyword) from sogoulog_1 where no1=2 and clickid=1;

99224

hive> select count(keyword) from sogoulog_1 where no1=3 and clickid=1;

50782

 

從排名第一URL來看,點選順序越小越多(首先被點到的可能性就越大)。

hive> select count(keyword) from sogoulog_1 where no1=1 and clickid=1;

279492

hive> select count(keyword) from sogoulog_1 where no1=1 and clickid=2;

79721

hive> select count(keyword) from sogoulog_1 where no1=1 and clickid=3;

39726

 

 

小結:

MapReduce對原始資料進行清洗,是本實驗的難點,要結合註釋看懂程式碼(資料清洗)。

hive對資料進行資料分析,找到隱含在資料中的規律/價值(資料探勘)。 

還可以做的是資料視覺化等。

 

完成! enjoy it!