最近作一个轻量文本搜索项目,在项目实行过程当中,若是使用余弦求网页类似度,不能适应海量网页查重。看了那本《这就是搜索引擎 核心技术详解》后,对simhash算法有必定的理解,而且喜欢上了这个算法。关于simhash的使用,看博客http://blog.csdn.net/u013209147/article/details/48227113 。git
如下是项目的算法。每次读取一个文档就进行查重,以便于适应往后用网络爬虫抓取网页,动态地进行查重得须要。查重的过程还行,simhash值在set中,此处还能够进一步优化。花时间比较多的在于对网页的处理上(分词,词频统计等),还好这只是预处理,不是响应客户端。github
1、预处理算法
一、DirScan.hpp 递归遍历语料文件夹,将全部文档的绝对路径保存到vector<string> oldVec 中;
二、DuplicateRemoval 对上述的 oldVec 进行遍历操做:
循环作如下操做:
1)根据vector<string>中的一个路径读取一篇网页到字符串。
2)使用"cppjiaba 工具"对字符串进行分词,词频统计,取topN个关键字。
3)使用"simhash 工具"将topN关键字映射成一个表明网页特征的64bit simhash值。
4)将"simhash"中的isEqual()方法,传入find_if(),将待选网页的64bit simhash与set<uint64_t>中的simhash值比较,判断海明距离与3(默认为3,能够自定义)的关系。
5)若是isEqual()返回true;则说明海明距离小于3,即断定此网页与已选网页中的某一篇重复。返回步骤 1)。
若是isEqual()返回false;则说明不重复,作进一步操做步骤 6)。
6)将simhash值插入到set<uint64_t>中,并将此网页的路径加入到新的数组vector<string> newVec中。
7)循环上述操做,指导下标指向oldVec的结尾。结束后获得一个装有不重复网页的路径的数组 newVec。
编程
类或者模块之间的关系:json
cppjiaba <- dict
Simhasher.hpp <- cppjiaba
Simhasher.hpp <- jenkins.h(产生哈希值的工具)
DuplicateRemoval.hpp <-Simhasher.hpp
最终咱们使用DuplicateRemoval就能够完成网页去重的工做。
三、FileHandle.hpp 对网页进行格式化
将DuplicateRemoval处理的结果传给FilaHandle.cpp的对象,就能够获得一个网页库文件和一个文件偏移文件。
四、BuildIndex 建字典(哈希加链表优化词典)和倒排文件(……,<docid,TF,weight>,……)
使用Cppjieba,根据偏移文件读取网页库,对每一篇网页进行分词,词频统计……。
2、服务端编程
1)接收客户端请求的字符串str
2)使用cppjieba分词库对str进行分词(使用full模式)
3)将分词结果保存到一个数组中
4)对数组进行遍历操做,根据倒排文件寻找对应的网页,读取出的网页根据单词的权重进行排序。
5)读取网页,并用XMLParser.hpp(已经封装好)解析XML格式的文档数组
6)用cppjson工具将解析结果封装成json字符串返回客户端。网络
以上仅供参考,可能还会有优化的地方。项目的代码还差一点完成,以后见github。工具
版权声明:本文为博主原创文章,未经博主容许不得转载。优化