使用simhash库来进行网页去重
首先感谢作者yanyiwu贡献的开源项目https://github.com/yanyiwu/simhash。在做项 目过程中,翻了一遍《这就是搜索引擎 核心技术详解》这本书的查重算法,在众多的算法中,我选择了simhash。这个算法的魅力在于,
它把文本内容的相似性,转换为哈希值的相似性,很好理 解,效率也高,再说,谷歌也用着。关于本算法的一些介绍,在yanyiwu大神的博客
http://yanyiwu.com/work/2014/01/30/simhash-shi-xian-xiang-jie.html 中也有介绍。对这个 算法的实现逻辑之后,开始来对这个算
法的使用。既然大神已经贡献出了源码,那我们首先要去学会如何使用这个宝贵的东西。因此,我对大神yanyiwu封装 的Simhasher类的成员
函数的功能及其参数阐述自己的理解,学会如何使用这些接口。关于这些接口的实现,
请参见github上的源码 /simhash/src/Simhasher.hpp.
以下是函数使用说明:
1 #ifndef SIMHASH_SIMHASHER_HPP 2 #define SIMHASH_SIMHASHER_HPP 3 4 #include "CppJieba/KeywordExtractor.hpp" //使用结巴分词库下的"关键字提取头文件" 5 #include "hashes/jenkins.h" //使用jenkins.h进行特征到哈希值的转换 6 7 namespace Simhash 8 { 9 using namespace CppJieba; 10 class Simhasher: public NonCopyable 11 { 12 private: 13 enum{BITS_LENGTH = 64}; 14 jenkins _hasher; //对象成员,用于获取哈希值,组合关系 15 KeywordExtractor _extractor; //jieba分词库中的类作为Simhash的类成员,组合关系 16 public: 17 /****************构造函数*****************/ 18 /* 传入: 19 * 1)词典路径 20 * 2)模式路径 21 * 3)idf路径 22 * 4)停用词路径 23 */ 24 25 //赋值 _extractor 的构造与析构 26 Simhasher(const string& dictPath, const string& modelPath, const string& idfPath, const string& stopWords) 27 : _extractor(dictPath, modelPath, idfPath, stopWords) 28 {} 29 30 //析构函数 31 ~Simhasher(){}; 32 33 /********以下是Simhash的类成员函数*********/ 34 public: 35 /* 1 */ bool extract(const string& text, vector<pair<string,double> > & res, size_t topN) const; 36 /* 功能: 37 * 抽取关键字,内部调用了_extractor.extract(); 38 * 参数: 39 * (1)text 是传入的将要进行抽取关键字的字符串 40 * (2)res 装“关键字/权重”的数组 41 * (3)topN 词频最高的前N个单词 42 */ 43 44 45 46 /* 2 */bool make(const string& text, size_t topN, vector<pair<uint64_t, double> >& res) const; 47 /* 功能: 48 * 返回能代表text这篇文章内容的topN个关键字的<二进制hash值,权重>对的数组。 49 * 参数: 50 * (1)text 是传入的将要进行抽取关键字的字符串 51 * (2)topN 词频最高的前N个单词 52 * (3)res topN个关键字对应的64bit hash值组成的数组 53 */ 54 55 56 57 /* 3 */bool make(const string& text, size_t topN, uint64_t& v64) const 58 /* 功能: 59 * 返回能代表text这篇文章内容的topN个关键字映射成的simhash值 60 * 参数: 61 * (1)text 是传入的将要进行抽取关键字的字符串 62 * (2)topN 词频最高的前N个单词 63 * (3)v64 topN个关键字对应的64bit simhash值 64 */ 65 66 67 68 /* 4 */static bool isEqual(uint64_t lhs, uint64_t rhs, unsigned short n = 3); 69 /* 功能: 70 * 计算并判断 lhs 与 rhs 的海明距离是否小于n(默认为3) 71 * 参数: 72 * (1) lhs ,rhs 左右(不分左右)的64bit simhash值 73 * (2) n 海明距离的上限值 74 */ 75 76 77 78 /* 5 */static void toBinaryString(uint64_t req, string& res); 79 /* 功能: 80 * 将uint64_t的hash值转变成64bit二进制,便于进行海明距离计算 81 * 参数: 82 * (1) req uint64_t型的哈希值 83 * (2) res 二进制字符串 84 */ 85 86 87 88 /* 6 */static uint64_t binaryStringToUint64(const string& bin); 89 /* 功能: 90 * 将64bit二进制转变成uint64_t的hash值 91 * 参数: 92 * (1) bin 二进制字符串 93 */ 94 }; 95 }
手与大脑的距离决定了理想与现实的相似度