搜狗日志分析

数据格式

1
搜索时间 	用户ID 	[查询词] 	该URL在返回结果中的排名 	用户点击的顺序号 	用户点击的URL

需求分析

  • 首先要做的是数据的清洗和转换
    • 过滤掉无效的数据
      • 无效的数据是读取的数据的长度小于6就排除(通过filter算子实现)
    • 筛选出有用的字段
      • 筛选出的字段方便我们后续的分析

需求1:

  • 统计热门搜索词Top10【出现次数最多前10个==搜索词==】 
    • 预期结果:(搜索词,出现次数)
    • 实现思路:
      • 1, 读取数据, 数据清洗
      • 2, 将搜索内容通过分词器分解(每个词作为一个独立的单元)
      • 3, 对每一个词作标记,出现一次
      • 4, 通过reduceByKey算子计算每个词出现的次数

需求2

  • 统计所有用户所有搜索中最大搜索次数、最小搜索次数、平均搜索次数
    • 预期结果:最大搜索次数、最小搜索次数、平均搜索次数
    • 实现思路:
      • 1, 读取数据, 数据清洗
      • 2, 构建(userid, 查询词设为1)kv键值对格式的数据
      • 3, 进行reduceByKey聚合操作,得到每个用户的总的搜索次数
      • 4, 比较所有用户, 求出最大搜索次数、最小搜索次数、平均搜索次数

需求3

  • ==统计一天每小时搜索量==并按照搜索量降序排序【统计每个小时数据量,按照数据量降序排序】
    • 预期结果:(小时,搜索量),最多24行
    • 实现思路:
      • 1, 读取数据, 数据清洗
      • 2, 构建KV类型的数据(hour, 1)
      • 3, 分组聚合
      • 4, 降序显示

Jieba中文分词器

什么是Jieba

jieba分词器是目前最好的 Python 中文分词组件,社区非常活跃,功能丰富,支持关键词提取、词性标注等。既然Jieba是个组件, 那必然是通过pip的方式下载.

安装方式

取决于你的解析器(interpreter)的位置.但最终应该离不开Anaconda这个工具包,所以要先切换虚拟环境.

1
2
conda activate base
pip install jieba -i https://pypi.tuna.tsinghua.edu.cn/simple/

使用方式

  • 模式

    • 全模式:将句子中所有可以组成词的词语都扫描出来, 速度非常快,但可能会出现歧义

      1
      jieba.cut("语句", cut_all=True)
    • 精确模式:将句子最精确地按照语义切开,适合文本分析,提取语义中存在的每个词

      1
      jieba.cut("语句", cut_all=False)
    • 搜索引擎模式:在精确模式的基础上,对长词再次切分,适合用于搜索引擎分词

      1
      jieba.cut_for_search("语句")

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
line = 'PySpark交互式编程'
# todo: 全模式分词
segment_list = jieba.cut(line, cut_all=True)
print(','.join(segment_list))
# todo: 精准模式
segment_list1 = jieba.cut(line, cut_all=False)
print(','.join(segment_list1))
# todo: 搜索引擎模式
segment_list2 = jieba.cut_for_search(line)
print(','.join(segment_list2))

"""
结果:
全模式分词: PySpark,交互,交互式,编程
精准模式: PySpark,交互式,编程
搜索引擎模式: PySpark,交互,交互式,编程
"""

DemoCode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from pyspark import SparkContext, SparkConf
import os
import jieba
import re

os.environ['JAVA_HOME'] = '/export/server/jdk'
os.environ['SPARK_HOME'] = '/export/server/spark' #Spark安装位置
os.environ["PYSPARK_PYTHON"] = "/export/server/anaconda3/bin/python3"
os.environ["PYSPARK_DRIVER_PYTHON"] = "/export/server/anaconda3/bin/python3"

if __name__ == '__main__':
conf = SparkConf().setMaster('yarn').setAppName('wordcount01')
sc = SparkContext(conf=conf)

# 数据格式 搜索时间 用户ID [查询词] 该URL在返回结果中的排名 用户点击的顺序号 用户点击的URL
# 读取文件, 数据清洗, 构建通用RDD
fileRdd = sc.textFile('hdfs://node1:8020/datas/input/sogou.tsv')
# print(fileRdd.take(3))
# print(fileRdd.count()) # 1724264
# 这里使用了\s匹配空白字符(space)
filterRdd = fileRdd.filter(lambda line: len(re.split("\\s+", line)) == 6)
# print(filterRdd.count()) # 1721708 -- 说明过滤是有作用的
# 构建通用RDD (搜索时间, 用户id, 查询词) 这里搜索时间只保留小时, 查询词需要去掉中括号
commonRdd = filterRdd.map(lambda line: (re.split('\\s+', line)[0][0:2],re.split('\\s+', line)[1], re.split('\\s+', line)[2][1:-1]))
# commonRdd格式为: ('00', '2982199073774412', '360安全卫士')

# 需求1: 求最热关键词top10 (先用jieba分词, 每个词转为word, 1的形式, 最后词频统计
# print(commonRdd.take(3))
# 定义黑名单关键词, 然后通过filter过滤 not in list
list = ['+', '的', '.', 'com', '原因']
top10 = commonRdd.map(lambda list: list[2]).\
flatMap(lambda x: jieba.cut(x, cut_all=False)).filter(lambda x: x not in list).\
map(lambda x: (x, 1)).\
reduceByKey(lambda x,y: x+y).\
sortBy(lambda x: x[1], ascending=False).\
take(10)
print(top10)

# 需求2: 求用户最大,最小平均搜索次数 (用户id, 访问次数)
need2Rdd = commonRdd.\
map(lambda list: (list[1], 1)).\
reduceByKey(lambda x,y: x+y).\
values()
print("最大访问次数", need2Rdd.max())
print("最小访问次数", need2Rdd.min())
print("平均访问次数", need2Rdd.mean())

# 需求3:统计一天每小时搜索量,并按照搜索量降序排序 (小时, 搜索量)
need3Rdd = commonRdd.\
map(lambda list: (list[0], 1)).\
reduceByKey(lambda x,y: x+y).\
sortBy(lambda x: x[1], ascending=False)
print(need3Rdd.top(10))

百度日志分析

字段分析

1
编号、时间、用户id,搜索关键字、用户点击的结果在搜索结果的排名,用户的点击次数、用户访问的网络地址

需求分析

  • (1) 读入百度搜索词文件文档,生成RDD

  • (2) 统计百度最热Top10搜索词及每个词的搜索次数,并降序排序

  • (3) 统计‘小说’关键词在每天各个时段的搜索次数,并降序排序

  • (4) 统计 用户点击的结果在搜索结果的排名 中排名在 1 到 10 的被点击的占比
    1 10%
    2 25%
    3 40%
    …..

  • (5) 统计最热门Top10网站的搜索用户数,并降序排序
    www.jd.com 1000
    www.qqq.com 800

CodeDemo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from pyspark import SparkContext, SparkConf
import os
import re
import jieba

os.environ['JAVA_HOME'] = '/export/server/jdk'
os.environ['SPARK_HOME'] = '/export/server/spark' #Spark安装位置
os.environ["PYSPARK_PYTHON"] = "/export/server/anaconda3/bin/python3"
os.environ["PYSPARK_DRIVER_PYTHON"] = "/export/server/anaconda3/bin/python3"

if __name__ == '__main__':
conf = SparkConf().setMaster('yarn').setAppName('wordcount01')
sc = SparkContext(conf=conf)
"""
# 编号、时间、用户id,搜索关键字、用户点击的结果在搜索结果的排名,用户的点击次数、用户访问的网络地址
- (1) 读入百度搜索词文件文档,生成RDD
- (2) 统计百度最热Top10搜索词及每个词的搜索次数,并降序排序 -- 搜索词, 次数
- (3) 统计‘小说’关键词在每天各个时段的搜索次数,并降序排序 -- 先filter过滤到小说, (时间, 次数)
- (4) 统计 用户点击的结果在搜索结果的排名 中排名在 1 到 10 的被点击的占比 -- 排名, 用户点击次数/总点击次数
1 10%
2 25%
3 40%
.....
- (5) 统计最热门Top10网站的搜索用户数,并降序排序 (网站, 1) -> (网站, 总搜索量)
www.jd.com 1000
www.qqq.com 800
"""
# 编号、时间、用户id,搜索关键字、用户点击的结果在搜索结果的排名,用户的点击次数、用户访问的网络地址
# 读取文件, 数据清洗, 得到通用RDD
fileRdd = sc.textFile('hdfs://node1:8020/datas/baidudemo')
print(fileRdd.take(2))
filterRdd = fileRdd.filter(lambda line: len(re.split('\\s+', line)) == 7)
commRdd = filterRdd.map(lambda line: (re.split('\\s+', line)[1][8:10], re.split('\\s+', line)[3], re.split('\\s+', line)[4], re.split('\\s+', line)[5], re.split('\\s+', line)[6]))
print(commRdd.take(2)) # ('00', '奇艺高清', '1', '1', 'http://www.qiyi.com/')
# 时间、搜索关键字、用户点击的结果在搜索结果的排名,用户的点击次数、用户访问的网络地址

# (2) 统计百度最热Top10搜索词及每个词的搜索次数, 并降序排序
black_list = ['的', '.', 'com']
top10Rdd = commRdd.\
flatMap(lambda list: jieba.cut(list[1], cut_all=False)).\
filter(lambda x:x not in black_list).\
map(lambda word: (word,1)).\
reduceByKey(lambda x,y:x+y).\
sortBy(lambda x: x[1], ascending=False).\
take(10)
print(top10Rdd)

# (3) 统计‘小说’关键词在每天各个时段的搜索次数,并降序排序 -- (时间, 关键字) -> 过滤到小说 -> (时间, 次数)
novelRdd = commRdd.map(lambda list: (list[0],list[1])).\
filter(lambda list: re.search('.*小说.*', list[1]) != None).\
map(lambda x: (x[0], 1)).\
reduceByKey(lambda x,y: x+y).\
sortBy(lambda x: x[1],ascending=False).\
take(10)
print(novelRdd)

# (4) 统计 用户点击的结果在搜索结果的排名 中排名在 1 到 10 的被点击的占比 -- 排名, 用户点击次数/总点击次数
clickNumRdd = commRdd.\
filter(lambda list: 1 <= int(list[2]) <= 10).\
map(lambda list: (list[2], list[3])).\
reduceByKey(lambda x,y: x+y)
print(clickNumRdd.take(9))

# (5) 统计最热门Top10网站的搜索用户数,并降序排序 (网站, 1) -> (网站, 总搜索用户数)
hotWebRdd = commRdd.\
map(lambda list: (list[4],1)).\
reduceByKey(lambda x,y:x+y).\
sortBy(lambda x:x[1],ascending=False).\
take(10)
print(hotWebRdd)