Spark+Jieba实现中文分词
本案例使用jieba分词,jieba 是目前最好的 Python 中文分词组件,使用Spark同样也能实现中文分词。实现步骤如下:
1.导入依赖
<dependency>
<groupId>com.huaban</groupId>
<artifactId>jieba-analysis</artifactId>
<version>1.0.2</version>
</dependency>
2.数据样本截取
8920397333 王铮亮 时间都去哪了 《私人订制》插曲
8920408333 Locked Out Of Heaven 音乐高清视频MV
8920422333 影视-心上人啊快给我力量KTV(电影《神圣的使命》插曲
8920491333 068_奥特曼
8920492333 影视-幸福不会从天降KTV(电影《我们村里的年轻人》插
8920527333 邓紫棋 GEM 2013 X.X.X. LIVE 演唱会 【全场高清】
8920529333 067_外婆的澎湖湾
8920588333 卓依婷-纸飞机
8920622333 073_小红帽儿歌
8920623333 072_字母歌
8920624333 影视-星星知我心KTV(台湾电视剧《星星知我心》主题曲
8920650333 2014蔡依林新年歌曲《新年喜洋洋》
8920702333 《Love Me》Justin Bieber感谢歌迷最新单曲
8920717333 075_只要妈妈露笑脸
8920731333 外婆的澎湖湾(电音dj舞曲)
8920745333 新西兰小伙,罗艺恒 加油 不插电现场版
8920787333 少女部落格2014迎新年首播MV《恭喜好运来》
8920791333 天路MV-韩红
8920845333 初音未来PV【世界第一公主殿下】
8920849333 曼莉(dj电音舞曲)
8920888333 《我是歌手》第四场无歌单惊呆众歌手!
8920909333 【MV首播】野人-EveN MV(完整HD版)
8920922333 影视新势力 美女偶像 景甜 风--- 电影 战国 主题曲
8920944333 【刘德华高清MV合集】真永远 高清
8920956333 郑源-难道爱一个人有错吗[高清MV街](流畅)
8920982333 500.甄妮 鲁冰花 演唱会 热门MV MTV 音乐高清排行榜
8921010333 少女时代 Gee Japanese ver
.................
3.代码实现
object FenCi {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession.builder()
.master("local[1]")
.appName("FenCi")
.config("spark.seriailzer", "org.apache.spark.serializer.KryoSerializer")
.getOrCreate()
val sc = spark.sparkContext
// source
val in_file = sc.textFile("music.small")
// 把每一行变成array
val sourceRDD: RDD[Array[String]] = in_file.mapPartitions(iter => {
iter.map(x => {
x.trim.split("\t")
})
})
// sourceRDD.take(10).foreach(x => x.foreach(println))
/**结果
* 8920408333
* Locked Out Of Heaven 音乐高清视频MV
* 8920422333
* 影视-心上人啊快给我力量KTV(电影《神圣的使命》插曲
* 8920491333
* 068_奥特曼
* 8920492333
* 影视-幸福不会从天降KTV(电影《我们村里的年轻人》插
* 8920527333
* 邓紫棋 GEM 2013 X.X.X. LIVE 演唱会 【全场高清】
* 8920529333
* 067_外婆的澎湖湾
* 8920588333
* 卓依婷-纸飞机
* 8920622333
* 073_小红帽儿歌
* 8920623333
* 072_字母歌
*/
// 取数组的第二个元素 内容
val contentRDD = sourceRDD.mapPartitions(iter => {
iter.map(x => {
x(1).trim
})
})
// contentRDD.take(10).foreach(println)
/**
* 王铮亮 时间都去哪了 《私人订制》插曲
* Locked Out Of Heaven 音乐高清视频MV
* 影视-心上人啊快给我力量KTV(电影《神圣的使命》插曲
* 068_奥特曼
* 影视-幸福不会从天降KTV(电影《我们村里的年轻人》插
* 邓紫棋 GEM 2013 X.X.X. LIVE 演唱会 【全场高清】
* 067_外婆的澎湖湾
* 卓依婷-纸飞机
* 073_小红帽儿歌
* 072_字母歌
*/
// 分词
val fenciRDD = contentRDD.mapPartitions(iter => {
iter.map(x => {
fenci_func(x)
})
})
// fenciRDD.take(10).foreach(println)
/**
* [影视-心上人啊快给我力量KTV(电影《神圣的使命》插曲, 影视, 心上人, 快给我, 力量, KTV, 电影, 神圣, 使命, 插曲]
* [068_奥特曼, 068, 奥特曼]
* [影视-幸福不会从天降KTV(电影《我们村里的年轻人》插, 影视, 幸福, 不会, 天降, KTV, 电影, 我们, 村里, 年轻人]
* [邓紫棋 GEM 2013 X.X.X. LIVE 演唱会 【全场高清】, 邓紫棋, GEM, 2013, . , LIVE, 演唱会, 【, 全场, 高清]
* [067_外婆的澎湖湾, 067, 外婆, 澎湖湾]
* [卓依婷-纸飞机, 卓依婷, 纸飞机]
* [073_小红帽儿歌, 073, 小红帽, 儿歌]
* [072_字母歌, 072, 字母]
*/
// 输出格式整理
val resultRDD = fenciRDD.mapPartitions(iter => {
iter.map(x => {
val sb = new StringBuilder
sb.append("\t").append(x)
})
})
resultRDD.take(10).foreach(println)
/**
* [王铮亮 时间都去哪了 《私人订制》插曲, 铮亮, 时间, 《, 私人, 订制, 插曲]
* [Locked Out Of Heaven 音乐高清视频MV, Locked, Out, Of, Heaven, 音乐, 高清, 视频, MV]
* [影视-心上人啊快给我力量KTV(电影《神圣的使命》插曲, 影视, 心上人, 快给我, 力量, KTV, 电影, 神圣, 使命, 插曲]
* [068_奥特曼, 068, 奥特曼]
* [影视-幸福不会从天降KTV(电影《我们村里的年轻人》插, 影视, 幸福, 不会, 天降, KTV, 电影, 我们, 村里, 年轻人]
* [邓紫棋 GEM 2013 X.X.X. LIVE 演唱会 【全场高清】, 邓紫棋, GEM, 2013, . , LIVE, 演唱会, 【, 全场, 高清]
* [067_外婆的澎湖湾, 067, 外婆, 澎湖湾]
* [卓依婷-纸飞机, 卓依婷, 纸飞机]
* [073_小红帽儿歌, 073, 小红帽, 儿歌]
* [072_字母歌, 072, 字母]
*/
sc.stop()
}
def f1(x:String):Array[String] = {
x.trim.split(" ")
}
/**
* 分词方法
* @param x
* @return
*/
def fenci_func(x:String): util.ArrayList[String] = {
import scala.collection.JavaConversions._
val word_list = new JiebaSegmenter().sentenceProcess(x.trim)
val ls = new util.ArrayList[String]()
ls.add(x.trim)
word_list.foreach(word => {
if (word.length > 1) {
ls.add(word)
}
})
ls
}
}
4.总结
/**
* 使用process()结果是列表套列表,里面的每个小列表中元素依次是
* [分好的词, 分好的词的第一个字符在文本字符数组的索引, 分好的词的最后一个字符在文本字符数组的索引的下一个索引]
* INDEX:精准的切开,用于对用户查询词分词;
* SEARCH:长词再切分,提高召回率。
* 可以看到核心在于:
* 1、内部包含一个字典
* 2、分词逻辑
* 3、不同模式的切分粒度
*/
val str = "北京大学生活动中心"
val ss = new JiebaSegmenter().sentenceProcess(str).toString
// [北京, 大学生, 活动中心]
val ss2 = new JiebaSegmenter().process(str, SegMode.INDEX).toString
// [[北京, 0, 2], [大学, 2, 4], [学生, 3, 5], [大学生, 2, 5], [活动, 5, 7], [中心, 7, 9], [活动中心, 5, 9]]
val ss3 = new JiebaSegmenter().process(str, SegMode.SEARCH).toString
// [[北京, 0, 2], [大学生, 2, 5], [活动中心, 5, 9]]