hadoop中文分词、词频统计及排序

需求如下:

有如图所示的输入文件。其中第一列代表ip地址,之后的偶数列代表搜索词,数字(奇数列)代表搜索次数,使用"\t"分隔。现在需要对搜索词进行分词并统计词频,此处不考虑搜索次数,可能是翻页,亦不考虑搜索链接的行为。

这里中文分词使用了IK分词包,直接将源码放入src中。感谢IK分词。

程序如下:

<span style="font-size:14px;">package seg;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;

/**
 * @author zhf
 * @version 创建时间:2014年8月16日 下午3:04:40
 */
public class SegmentTool extends Configured implements Tool{
	public static void main(String[] args) throws Exception {
		int exitCode = ToolRunner.run(new SegmentTool(), args);
		System.exit(exitCode);
	}

	@Override
	public int run(String[] arg0) throws Exception {
		Configuration conf = new Configuration();
		String[] args = new GenericOptionsParser(conf,arg0).getRemainingArgs();
		if(args.length != 2){
			System.err.println("Usage:seg.SegmentTool <input> <output>");
			System.exit(2);
		}
		Job job = new Job(conf,"nseg.jar");
		FileSystem fs = FileSystem.get(conf);
		if(fs.exists(new Path(args[1])))
			fs.delete(new Path(args[1]),true);
		job.setJarByClass(SegmentTool.class);
		job.setMapperClass(SegmentMapper.class);
		job.setCombinerClass(SegReducer.class);
		job.setReducerClass(SegReducer.class);
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);

		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);

		FileInputFormat.addInputPath(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		return job.waitForCompletion(true) ? 0 : 1;
	}

	public static class SegmentMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
		private IKSegmenter iks = new IKSegmenter(true);
		private Text word = new Text();
		private final static IntWritable one = new IntWritable(1);
		public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException{
			String line = value.toString().trim();
			String[] str = line.split("\t");
			for(int i=1;i<str.length;i+=2){
				String tmp = str[i];
				if(tmp.startsWith("http"))
					continue;
				List<String> list = segment(tmp);
				for(String s : list){
					word.set(s);
					context.write(word, one);
				}
			}
		}
		private List<String> segment(String str) throws IOException{
			byte[] byt = str.getBytes();
			InputStream is = new ByteArrayInputStream(byt);
			Reader reader = new InputStreamReader(is);
			iks.reset(reader);
			Lexeme lexeme;
			List<String> list = new ArrayList<String>();
			while((lexeme = iks.next()) != null){
				String text = lexeme.getLexemeText();
				list.add(text);
			}
			return list;
		}
	}
	public static class SegReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
		private IntWritable result = new IntWritable();
		public void reduce(Text key,Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{
			int sum = 0;
			for(IntWritable val : values)
				sum += val.get();
			result.set(sum);
			context.write(key, result);
		}
	}

}</span>

使用的hadoop环境为:Hadoop 2.3.0-cdh5.0.0。需要引入三个hadoop相关的jar : hadoop-mapreduce-client-core-2.0.0-cdh4.6.0.jar、hadoop-common-2.0.0-cdh4.6.0.jar、commons-cli-1.2.jar。

打包后,执行命令:yarn jar seg.jar seg.SegmentTool /test/user/zhf/input /test/user/zhf/output

输出结果如下:

<span style="font-size:18px;">阿迪达斯        1
附近    2
陈      22
陈乔恩  1
陈奕迅  1
陈毅    2
限额    4
陕西    4
除个别  1
隐私    1
隔壁    1
集成    4
集锦    1
雨中    2
雪      5
露      1
青      7
青岛    2</span>

但是并没有排序,如果数据量比较小,可以采用linux命令:sort -k2 -n -r kw_result.txt > kw_freq.txt进行排序。

数据量大的话,可以将结果导入Hive,因为只有两列了,hive -e "select key,count from kw_table sort by count desc;" > kw_freq.txt 即可得到有序的结果。

亦可以将之前的ouput作为下一个job的input,实现排序。需要反转map输出的key和value。

代码如下:

<span style="font-size:14px;">package seg;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparator;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

/**
 * @author zhf
 * @email [email protected]
 * @version 创建时间:2014年8月16日 下午4:51:00
 */
public class SortByFrequency extends Configured implements Tool{
	public static void main(String[] args) throws Exception {
		int exitCode = ToolRunner.run(new SortByFrequency(), args);
		System.exit(exitCode);
	}

	@Override
	public int run(String[] arg0) throws Exception {
		Configuration conf = new Configuration();
		String[] args = new GenericOptionsParser(conf,arg0).getRemainingArgs();
		if(args.length != 2){
			System.err.println("Usage:seg.SortByFrequency <input> <output>");
			System.exit(2);
		}
		Job job = new Job(conf,"nseg.jar");
		FileSystem fs = FileSystem.get(conf);
		if(fs.exists(new Path(args[1])))
			fs.delete(new Path(args[1]),true);
		job.setJarByClass(SortByFrequency.class);
		job.setMapperClass(SortMapper.class);
		job.setReducerClass(SortReducer.class);
		job.setSortComparatorClass(DescComparator.class);
		job.setMapOutputKeyClass(IntWritable.class);
		job.setMapOutputValueClass(Text.class);

		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);

		FileInputFormat.addInputPath(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		return job.waitForCompletion(true) ? 0 : 1;
	}

	public static class SortMapper extends Mapper<LongWritable,Text,IntWritable,Text>{
		public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException{
			String str[] = value.toString().split("\t");
			context.write(new IntWritable(Integer.valueOf(str[1])), new Text(str[0]));
		}
	}
	public static class SortReducer extends Reducer<IntWritable,Text,Text,IntWritable>{
		private Text result = new Text();
		public void reduce(IntWritable key,Iterable<Text> values,Context context) throws IOException, InterruptedException{
			for(Text val : values){
				result.set(val);
				context.write(result, key);
			}
		}
	}
	public static class DescComparator extends WritableComparator{

		protected DescComparator() {
			super(IntWritable.class,true);
		}

		@Override
		public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3,
				int arg4, int arg5) {
			return -super.compare(arg0, arg1, arg2, arg3, arg4, arg5);
		}
		@Override
		public int compare(Object a,Object b){
			return -super.compare(a, b);
		}
	}
}</span>

head查看的结果如下:

的      175
上海    158
上      85
都市    76
在      71
ppt     64
运输    58
电视    58
式      58
2       52

hadoop中文分词、词频统计及排序

时间: 2024-10-29 19:13:34

hadoop中文分词、词频统计及排序的相关文章

Hadoop的改进实验(中文分词词频统计及英文词频统计)(4/4)

声明: 1)本文由我bitpeach原创撰写,转载时请注明出处,侵权必究. 2)本小实验工作环境为Windows系统下的百度云(联网),和Ubuntu系统的hadoop1-2-1(自己提前配好).如不清楚配置可看<Hadoop之词频统计小实验初步配置> 3)本文由于过长,无法一次性上传.其相邻相关的博文,可参见<Hadoop的改进实验(中文分词词频统计及英文词频统计) 博文目录结构>,以阅览其余三篇剩余内容文档. (五)单机伪分布的英文词频统计Python&Streamin

实验二-2 Eclipse&amp;Hadoop 做英文词频统计进行集群测试

  创建目录上传英文测试文档(如果已有则无需配置).a.dfs上创建input目录 [email protected]:~/data/hadoop-2.5.2$bin/hadoop fs -mkdir -p input b.把hadoop目录下的README.txt拷贝到dfs新建的input里 [email protected]:~/data/hadoop-2.5.2$bin/hadoop fs -copyFromLocal README.txt input —————————————————

利用Hadoop streaming 进行词频统计

创建一个文件夹 bin/hdfs dfs -mkdir /input 将要统计的文件上传到hadoopbin/hadoop fs -put /test.txt /input 利用hadoop进行词频统计bin/hadoop jar share/hadoop/tools/lib/Hadoop-streaming-2-9-2.jar –input /test.txt –output /user/results.txt –mapper /bin/cat -reducer /usr/bin/wc 删除r

流量汇总(自定义jar包,在hadoop集群上 统计,排序,分组)之统计

小知识点: half:关机 yarn端口:8088 删除hdfs目录:hadoop fs -rm -r /wc/output namenode两个状态都是standby原因:zookeeper没有比hdfs先启动 现在来做一个流量统计的例子: 首先数据是这样一张表:见附件 统计:(代码) 1,flowbean: package cn.itcast.hadoop.mr.flowsum; import java.io.DataInput; import java.io.DataOutput; imp

中文分词实践(基于R语言)

背景:分析用户在世界杯期间讨论最多的话题. 思路:把用户关于世界杯的帖子拉下来,然后做中文分词+词频统计,最后将统计结果简单做个标签云,效果如下: 后续:中文分词是中文信息处理的基础,分词之后,其实还有特别多有趣的文本挖掘工作可以做,也是个知识发现的过程,以后有机会再学习下. ================================================== * 中文分词常用实现: 单机:R语言+Rwordseg分词包 (建议数据量<1G) 分布式:Hadoop+Smallse

词频统计英文和统计中文的区别

通常我们做英文词频统计的时候,我们可能会采用单词树,或者map等等. 但是,在进行中文的词频统计的时候,中文之间没有空格和符号,不像在英 文词频统计一样,英文之间是有空格和符号的.所以,相对于英文来说,中 文词频统计比较难.主要是不好提取中文字通常我们在提取中文时候会进行 划分,通过汉字的关联等等来进行划分,提取.

实验二-3 Hadoop&amp;Paoding 中文词频统计

  参考教程 在Hadoop上使用庖丁解牛(较复杂,并未采用,可以之后试试) http://zhaolinjnu.blog.sohu.com/264905210.html Lucene3.3.Lucene3.4中文分词——庖丁解牛分词实例(屈:注意版本) http://www.360doc.com/content/13/0217/13/11619026_266124504.shtml 庖丁分词在hadoop上运行时的配置问题(采纳了一半,没有按照其所写配置dic属性文件) http://f.da

初学Hadoop之中文词频统计

1.安装eclipse 准备 eclipse-dsl-luna-SR2-linux-gtk-x86_64.tar.gz 安装 1.解压文件. 2.创建图标. ln -s /opt/eclipse/eclipse /usr/bin/eclipse #使符号链接目录 vim /usr/share/applications/eclipse.desktop #创建一个  Gnome 启动 添加如下代码: [Desktop Entry] Encoding=UTF-8 Name=Eclipse 4.4.2

在Hadoop上运行基于RMM中文分词算法的MapReduce程序

原文:http://xiaoxia.org/2011/12/18/map-reduce-program-of-rmm-word-count-on-hadoop/ 在Hadoop上运行基于RMM中文分词算法的MapReduce程序 23条回复 我知道这个文章标题很“学术”化,很俗,让人看起来是一篇很牛B或者很装逼的论文!其实不然,只是一份普通的实验报告,同时本文也不对RMM中文分词算法进行研究.这个实验报告是我做高性能计算课程的实验里提交的.所以,下面的内容是从我的实验报告里摘录出来的,当作是我学