前言
近日想学学Spark 比较新的Structured Streaming ,百度一轮下来,全都是千篇一律的wordcount ,很是无语。只好自己摸索,除了Dataframe的Select和Filter 操作还能做些什么处理。因为用的Python,用过Pandas,摸索中,想转Pandas去处理,结果readStream并不支持直接toPandas()这个方法。最后翻来官方API,发现了还有Dataframe还有一个强大的操作,并且能够在readStream中使用,那就是——UDF。
环境准备
- Hadoop 2.8.5
- Spark 2.4.3
- Python 3.7.3
- jieba (jieba分词工具,提供了TF-IDF关键词提取方法,pip install jieba)
程序下面的代码都是在交互式环境下执行,即pyspark下。
数据准备
id | title_zh | content_zh | publish_date | |
---|---|---|---|---|
假设CSV数据如上表格所示,分别表示文章id,标题,内容,发布时间。
有如下需求:提取标题的关键词,并将关键词添加到新列。(本来还有提取文章关键词,原理其实一样,就不多写了)
读取数据
读取csv文件有两步:定义schema,按照schema读取文件。
定义schema:
本例中,id为Integer类型,publish_date为TimestampType类型,其余为StringType。首先引入部分依赖:
from pyspark.sql.functions import udf
from pyspark.sql.types import StructType,StringType,IntegerType,TimestampType
定义一个StructType:
sdf=StructType().add('id',IntegerType())
sdf.add('title_zh',StringType()).add('content_zh',StringType())
sdf.add('publish_date',TimestampType())
设置监听文件夹,该文件夹当产生新的CSV文件时,spark会自动读取到stream,路径需要指明是hdfs:///或者file:///
rcsv=spark.readStream.options(header='true',multiline='true',inferSchema='true').schema(sdf).csv("file:///home/moon/文档/test")
通过rcsv.isStreaming判断是否是Stream
处理数据
处理数据分3步:
- 定义关键词提取方法,定义方法选取系数最高的词,剔除纯数字
- 将提取方法构造成Udf
- 利用Dataframe的“转换”方法调用Udf
最后选择输出模式、输出目地,输出结果。下面直接上代码,具体看注释:
#引入jieba依赖
import jieba
import jieba.analyse
def getTopWord(words):
if(words==[]):
return ""
wordc=0
while (words[wordc].isdigit()):
if(wordc>=len(words)-1):
return words[wordc]
wordc+=1
return words[wordc]
def getKeyword(ctx):
#extract_tags方法有个可选topK=N参数,提取N个词,但是这里要剔除纯数字要用另外的方法,所以使用它的默认值
word=getTopWord(jieba.analyse.extract_tags(ctx,withWeight=False))
return word;
#参数为(方法名,返回类型),方法可以是lambda,返回类型为必填。调用时,逐行调用udf
getKeyword_udf=udf(getKeyword,StringType())
#对['title_zh']这一列使用udf方法,并使用select生成新列,alias()定义别名,最后得到新的readStream
ncsv=rcsv.select('id','title_zh',getKeyword_udf(rcsv['title_zh']).alias('title_zh_keyword'),'publish_date')
#设置输出模式为update,还有complete和Append;输出到命令行。更详细我也说不清,建议看官方文档。
query=ncsv.writeStream.outputMode('update').format("console").start()
结果
上面的全部代码,在pyspark中,一条条输入代码就行了,路径根据自己实际替换,数据内容和类型可以根据自己喜好做调整。
本例的CSV文件如图:
执行结果图如下:
PS:小姐姐微博@只是简言 ,侵删~(反正我是不信有人会来举报我~)