使用storm统计英文版<<圣经>>的词频
我估计自己是疯掉了.....
刚入门storm,就先硬生生的来杠这部著作......
我先擦一把汗哈,然后呢,整个流程需要五个步骤,希望大家都可以得到属于自己的统计数据
1.下载圣经英文版,并修改一部分内容,例如标点
2.参考我的另一篇博客,那里面几乎是源码(只改两个类)
3.修改源码
4.准备枕头
5.抬头看结果
- 把所有逗号, 替换为""
- 把所有句号. 替换为" "(注意有空格)
- 把所有分号; 替换为""
- 把所有问号? 替换为""
- 把所有冒号: 替换为""
- 把所有左括号( 替换为" "(注意有空格)
- 把所有右括号) 替换为""(没有空格)
- (进阶项):替换所有数字为 ""
- (进阶项):替换所有表述为 "章节"含义的单词为""
请先参考我的博客:http://blog.csdn.net/weixin_35757704/article/details/77246313
这篇博客思路很简单,十分基础,参考它是因为我的这个就是在那篇博客源码的基础上改进来的
三.修改源码
这里面有具体的代码,我们只需要简单修改两个类就可以:
CreateSpout 修改
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import backtype.storm.utils.Utils;
import org.joda.time.DateTime;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Map;
/**
* 创建数据源
*/
public class CreateSpout extends BaseRichSpout {
private SpoutOutputCollector collector;
private String[] sentences = null; //为数据的总容量
String pathname;
File filename;
InputStreamReader reader;
BufferedReader br;
private String read() {
try {
String line = "";
line = br.readLine();
if (line != null) {
return line;
} else {
Utils.sleep(200000000);
}
} catch (Exception e) {
}
return "null";
}
@Override
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
this.collector = spoutOutputCollector;
try {
pathname = "C:\\storm\\storm_Pro\\kjv.txt";
filename = new File(pathname);
reader = new InputStreamReader(
new FileInputStream(filename));
br = new BufferedReader(reader);
} catch (Exception e) {
}
}
@Override
public void nextTuple() {
sentences = new String[]{read()};
/*storm会循环的调用这个方法*/
/*线程进行休眠,10s发送一次数据,在这10s内,让其余工作进行*/
Utils.sleep(100);
//获得数据源
System.out.println(new DateTime().toString("HH:mm:ss") + "--------------CreateSpout 开始发送数据----------");
this.collector.emit(new Values(sentences));
}
@Override
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("sentence"));
}
}
对这个类的修改,就是把数据源修改一下,从本地文件 kjv.txt读取,这也是<<圣经>>英文版的txt文件.大家也可以从其他地方下载.
PrintBolt 修改
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.tuple.Tuple;
import backtype.storm.utils.Utils;
import org.joda.time.DateTime;
import java.util.Map;
public class PrintBolt extends BaseRichBolt {
@Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
}
@Override
public void execute(Tuple input) {
System.out.println(new DateTime().toString("HH:mm:ss") + "--------------------final bolt 开始运行--------------------");
Map<String, Integer> counts = (Map<String, Integer>) input.getValue(0);
/*最后一个阶段,可以持久到mysql等数据库中*/
System.out.println(justForm(20 - 8) + "key" + justForm(20 - 8) + " " + "value");
try {
System.out.println("/////////////////////////////////////////////////////////");//与之前的打印信息分隔,直观的得到结果
for (Map.Entry<String, Integer> kv : counts.entrySet()) { /*这里的justForm()函数是为了保证格式一致*/
System.out.println(kv.getKey() + justForm(kv.getKey().length()) + " 频数 : " + kv.getValue());
}
} catch (Exception e) {
System.out.println("/////////////////////////////////////////////////////////////////////得到一个错误的值");
}
try {
Utils.sleep(60000);
}catch (Exception e){
}
}
private String justForm(int length) {
for (int i = 0; i < 20 - length; i++) {
System.out.print(" ");
}
return "";
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
}
}
对结果打印的代码进行修改是因为我们都知道,这种事情不是一时半会能完成的,因此这里设置一个等待的线程,不用实时的打印结果,只需要1分钟打印一次就好,不过我测试了一下,虚拟机win8.1+8G内存+SSD+i7-7700HQ的两个核心,也使用了20+分钟,下图是我在宿主机上截取的当时的数据:四.准备枕头
点一下运行,能正常跑两分钟,观察是不是死循环,如果一切正常,就可以倒头睡觉了
五.抬头看结果
下图有点恐怖,密集型恐惧症患者请捂脸.....
我的编译器是Intellij IDEA,它可以在控制台保存相当多的数据,所以可以都得到,其他的编辑器我就不是很了解了,如果为了以防万一,可以直接打印到本地文件中
而且如果你能够观察到右侧滑块的位置的话,那么你就可以知道为什么会有第四步了.....
大家可能注意到了,有许多频数只是1,大致翻译就是不同篇章的第1节,第二节等,因此这个筛选条件是有很大的改进空间的.
期待大家可以得到更好的筛选结果.大笑
上一篇: 实现Nginx的反向代理和负载均衡(二)
下一篇: nginx反向代理和负载均衡实现