搜狗日誌查詢分析 (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!