搜狗案例
数据例子
字段含义:访问时间,用户id,[]里面是用户输入搜索内容,url结果排名,用户点击页面排序,用户点击URL
字段与字段之间的分隔符号为 \t和空格 (制表符号)
要求:
- 统计每个关键词出现了多少次,关键词需要根据搜索的内容进行分词
- 统计每个用户每个搜索词点击的次数
- 统计每个小时点击次数
0、清洗
清洗过程:将不完整的数据进行过来,这里使用到filter方法进行数据过滤
def filterFun(item):
arr = item.split('\t')
return len(arr) == 6
1、需求1: 统计每个关键词出现了多少次
关键点:分词,分词的方式,可以使用jieba
这个库进行分词
import jieba
keyword = "你好中国"
jieba.lcut(keyword)
# 结果: ["你好","中国"]
通过jieba分词后,产生的是一个数组,所以我们对这个数据进行一次遍历,将数据通过字符串的方式拼凑起来,比如上面的情况:
“你好中国” => [“你好”,“中国”] => “你好,中国”
def mapFun(item):
keyword = item.split("\t")[2]
subKeyword = re.sub("[\[\]]", "", keyword)
keyArr = jieba.lcut(subKeyword)
resStr = ''
for i in keyArr:
resStr = resStr + i + ","
resStr = resStr.strip(",")
return resStr
然后就回到了熟悉的flatMap
-> map
-> reduceByKey
环节,完整代码如下
import re
import jieba
from pyspark import SparkContext, SparkConf
import os
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
def filterFun(item):
arr = item.split('\t')
return len(arr) == 6
def mapFun(item):
keyword = item.split("\t")[2]
subKeyword = re.sub("[\[\]]", "", keyword)
keyArr = jieba.lcut(subKeyword)
resStr = ''
for i in keyArr:
resStr = resStr + i + ","
resStr = resStr.strip(",")
return resStr
if __name__ == '__main__':
print("sougou test")
# 1. 创建SparkContext核心对象: spark Core 核心对象
conf = SparkConf().setAppName('pyspark_wd').setMaster('local[*]')
sc = SparkContext(conf=conf)
rdd_init = sc.textFile(name='file:///export/data/workspace/gz11_pyspark_parent/_02_spark_core/data/SogouQ.sample')
# print(rdd_init.take(10))
rdd_filter = rdd_init.filter(filterFun)
rdd_map = rdd_filter.map(mapFun)
rdd_flatMap = rdd_map.flatMap(lambda item: item.split(",")).map(lambda word: (word, 1))
rdd_reduce = rdd_flatMap.reduceByKey(lambda agg,curr: agg + curr)
print(rdd_reduce.collect())
2、需求2: 统计每个用户每个搜索词点击的次数
这里如果使用sql
的方式,可以理解为group by userid,word
,但是这里是编写spark代码,所以需要灵活一些,做法也相对简单,我们只需要将数据变成KV键值对,K就是userid
和word
的结合,V就是1,这样就构造出来了,接着再使用reduceByKey
就可以得到结果,完整代码如下
from pyspark import SparkContext, SparkConf
import os
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
def mapFun(item):
dataArr = item.split("\t")
return (dataArr[1] + "-" + dataArr[2],1)
if __name__ == '__main__':
print("sougou test")
# 1. 创建SparkContext核心对象: spark Core 核心对象
conf = SparkConf().setAppName('pyspark_wd').setMaster('local[*]')
sc = SparkContext(conf=conf)
rdd_init = sc.textFile(name='file:///export/data/workspace/gz11_pyspark_parent/_02_spark_core/data/SogouQ.sample')
rdd_res = rdd_init.map(mapFun).reduceByKey(lambda agg, curr: agg + curr)
print(rdd_res.collect())
3、需求3:统计每个小时点击次数
按小时进行统计,在数据中的字段1给到的是时分秒的时间格式,只需要取到字段1中的时,将其当作K,V则是1,再进行统计即可,完整代码如下:
from pyspark import SparkContext, SparkConf
import os
os.environ['SPARK_HOME'] = '/export/server/spark'
os.environ['PYSPARK_PYTHON'] = '/root/anaconda3/bin/python3'
os.environ['PYSPARK_DRIVER_PYTHON'] = '/root/anaconda3/bin/python3'
def mapFun(item):
timeStr = item.split("\t")[0].split(":")[0]
return (timeStr, 1)
if __name__ == '__main__':
print("sougou test")
# 1. 创建SparkContext核心对象: spark Core 核心对象
conf = SparkConf().setAppName('pyspark_wd').setMaster('local[*]')
sc = SparkContext(conf=conf)
rdd_init = sc.textFile(name='file:///export/data/workspace/gz11_pyspark_parent/_02_spark_core/data/SogouQ.reduced',minPartitions=4)
rdd_res = rdd_init.map(mapFun).reduceByKey(lambda agg, curr: agg + curr)
print(rdd_res.collect())