simhash应用-文章去重
来源:互联网 发布:数据可视化实战 pdf 编辑:程序博客网 时间:2024/05/16 06:40
在抓取新闻时,经常碰见的一个问题是会遇到重复新闻,针对重复新闻如果人工来判断工作量可想而知,好在,google提出了simhash,我们可以用simhash来判断两篇文章是否相似。simhash的原理请看这里:http://www.cnblogs.com/linecong/archive/2010/08/28/simhash.html
1、分词
拿到两篇文章,直接计算hash值显然是不可能的,最简单的想法是对文章进行分词,然后计算每个词的hash值,最后累加。
关于分词,再次强烈推荐ANSJ这个开源分词工具,请看这里:http://blog.csdn.net/zhaoxinfan/article/details/10403917
2、计算simhash值
具体看代码,在计算完simhash值后再判断两篇文章相似度,比较容易想到的是海明距离
import java.math.BigInteger;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.ansj.domain.Term;import org.ansj.splitWord.analysis.ToAnalysis;public class NewsSimHash { private String content; private BigInteger intSimHash; private String strSimHash; private int hashbits = 64;/** * * @param content newsContent * @param intSimHash指纹大整型表示 * @param strSimHash指纹字符串表示 * @param hashbits simhash位数,文档的特征向量维数 */ public NewsSimHash(String content) { this.content = content; this.intSimHash = this.simHash(); } public NewsSimHash(String content, int hashbits) { this.content = content; this.hashbits = hashbits; this.intSimHash = this.simHash(); } public BigInteger getIntSimHash() {return intSimHash;}public void setIntSimHash(BigInteger intSimHash) {this.intSimHash = intSimHash;}public String getStrSimHash() {return strSimHash;}public void setStrSimHash(String strSimHash) {this.strSimHash = strSimHash;}//收集关键词,计算权重 private List<String> getWord(String content){ List<String> word=new ArrayList<String>();try { List<Term> parse = ToAnalysis.parse(content);for (Term term : parse) { String line=term.getNatrue().toString(); String[] outline=new String[5]; outline=line.split(":"); term.getName().replaceAll("[\\pP‘’“”]", ""); if(!("".equals(term.getName())) ){ word.add(term.getName()); } }} catch (Exception e) {e.printStackTrace();}return word; } /** * 文档指纹生成 * 默认权重为 1 * @return */ public BigInteger simHash() { int[] v = new int[this.hashbits]; List<String> wordList = this.getWord(this.content); Iterator<String> it =wordList.iterator(); String keywords=""; //生成文档的和向量 while(it.hasNext()){ keywords = it.next(); System.out.print(keywords+" "); BigInteger keywordsHashValue = this.hash(keywords); for(int i = 0;i< this.hashbits;i++){ BigInteger bitMark =new BigInteger("1").shiftLeft(i); if(keywordsHashValue.and(bitMark).signum() == 1){ v[i]+= 1; }else{ v[i]-= 1; } } } System.out.print("\n"); //文档指纹生成 BigInteger fingerprint = new BigInteger("0"); StringBuffer simHashBuffer = new StringBuffer(); for (int i = 0; i < this.hashbits; i++) { if (v[i] >= 0) { fingerprint = fingerprint.add(new BigInteger("1").shiftLeft(i)); simHashBuffer.append("1"); }else{ simHashBuffer.append("0"); } } this.strSimHash = simHashBuffer.toString(); return fingerprint; } /** * 生成特征词的的hash值 * @param source * @return */ private BigInteger hash(String keywords) { if (keywords == null || keywords.length() == 0) { return new BigInteger("0"); } else { char[] sourceArray = keywords.toCharArray(); BigInteger x = BigInteger.valueOf(((long) sourceArray[0]) << 7); BigInteger m = new BigInteger("1000003"); BigInteger mask = new BigInteger("2").pow(this.hashbits).subtract( new BigInteger("1")); for (char item : sourceArray) { BigInteger temp = BigInteger.valueOf((long) item); x = x.multiply(m).xor(temp).and(mask); } x = x.xor(new BigInteger(String.valueOf(keywords.length()))); if (x.equals(new BigInteger("-1"))) { x = new BigInteger("-2"); } return x; } } /** * 指纹压缩 * 取两个二进制的异或,统计为1的个数,就是海明距离,确定两个文本的相似度,<3是近重复文本 * @param other * @return */ public int hammingDistance(NewsSimHash otherSimHash) { BigInteger x = this.intSimHash.xor(otherSimHash.intSimHash); int tot = 0;//x=0,海明距离为O; //统计x中二进制位数为1的个数 while (x.signum() != 0) { tot += 1; x = x.and(x.subtract(new BigInteger("1"))); } return tot; } public int hammingDistance(BigInteger simHash) { BigInteger x = this.intSimHash.xor(simHash); int tot = 0;//x=0,海明距离为O; //统计x中二进制位数为1的个数 while (x.signum() != 0) { tot += 1; x = x.and(x.subtract(new BigInteger("1"))); } return tot; } /** * 获取索引列表 * 如果海明距离取3,则分成四块,并得到每一块的bigInteger值 ,作为索引值使用 * @param simHash * @param distance * @return */ public List<BigInteger> genSimHashBlock(NewsSimHash simHash, int distance){ int eachBlockBitNum = this.hashbits/(distance+1); List<BigInteger> simHashBlock = new ArrayList<BigInteger>(); StringBuffer buffer = new StringBuffer(); for( int i = 0; i < this.intSimHash.bitLength(); i++){ boolean sr = simHash.intSimHash.testBit(i); if(sr){ buffer.append("1"); } else{ buffer.append("0");//补齐 } if( (i+1)%eachBlockBitNum == 0 ){//够十六位时 BigInteger eachValue = new BigInteger(buffer.toString(),2); System.out.println("----" +eachValue ); buffer.delete(0, buffer.length()); simHashBlock.add(eachValue); } } return simHashBlock; } //测试 public static void main(String[] args) { NewsSimHash ns=new NewsSimHash("中新网11月4日电 台当局防务部门负责人严明今天(4日)证实台军采购的最新型阿帕契直升机(AH-64E)已抵高雄港。陆军表示,吊挂顺利,正进行组装、地面测试。"+"严明上午在台当局“立法院”答询时指出,首批6架阿帕契直升机(AH-64E)已抵台。"+"台湾陆军指出,6架直升机以海运方式运抵高雄港,上午吊挂上岸作业顺利,正在进行组装,组装完后,会做地面测试,包括开车、旋翼转动等测试,相关过程军方全程保密。"+"陆军说,测试结束后,阿帕契直升机将在6日或7日飞抵陆军航空特战指挥部台南归仁基地;陆军也预计邀媒体参访,最新型的AH-64E直升机最快6日就能在民众面前亮相。"+"台湾地区向美国购买30架长弓阿帕契攻击直升机(AH-64E)是前美国总统布什(George W. Bush)政府在2008年宣布售台,总金额达新台币593.1亿元;除了美国外,台湾是第2个拥有此机型的地区。"); NewsSimHash ns1=new NewsSimHash("中新网11月4日电 据台湾“中央社”报道,台当局防务部门负责人严明今天(4日)证实台军采购的最新型阿帕契直升机(AH-64E)已抵高雄港。陆军表示,吊挂顺利,正进行组装、地面测试。"+"严明上午在台当局“立法院”答询时指出,首批6架阿帕契直升机(AH-64E)已抵台。"+"台湾陆军指出,6架直升机以海运方式运抵高雄港,上午吊挂上岸作业顺利,正在进行组装,组装完后,会做地面测试,包括开车、旋翼转动等测试,相关过程军方全程保密。"+"陆军说,测试结束后,阿帕契直升机将在6日或7日飞抵陆军航空特战指挥部台南归仁基地;陆军也预计邀媒体参访,最新型的AH-64E直升机最快6日就能在民众面前亮相。"+"台湾地区向美国购买30架长弓阿帕契攻击直升机(AH-64E)是前美国总统布什(George W. Bush)政府在2008年宣布售台,总金额达新台币593.1亿元;"); //simhash的二进制表示 System.out.println("simhash的二进制表示:"); System.out.println(ns.getStrSimHash()); System.out.println(ns1.getStrSimHash()); //simhash的BigInteger表示 System.out.println("simhash的BigInteger表示:"); System.out.println(ns.getIntSimHash()); System.out.println(ns1.getIntSimHash()); //ns1与ns的汉明距离, System.out.println("ns1与ns的汉明距离"); System.out.println(ns.hammingDistance(ns1)); }}
下面是程序的输出:
中新网 11月 4日 电 台当局 防务 部门 负责人 严明 今天 ( 4日 ) 证实 台军 采购 的 最新型 阿帕契 直升机 ( ah - 64 e ) 已 抵 高雄港 。 陆军 表示 , 吊挂 顺利 , 正 进行 组装 、 地面 测试 。 严明 上午 在 台当局 “ 立法院 ” 答询 时 指出 , 首批 6架 阿帕契 直升机 ( ah - 64 e ) 已 抵 台 。 台湾 陆军 指出 , 6架 直升机 以 海运 方式 运抵 高雄港 , 上午 吊挂 上岸 作业 顺利 , 正在 进行 组装 , 组装 完 后 , 会 做 地面 测试 , 包括 开车 、 旋翼 转动 等 测试 , 相关 过程 军方 全程 保密 。 陆军 说 , 测试 结束 后 , 阿帕契 直升机 将 在 6日 或 7日 飞抵 陆军 航空 特战 指挥部 台南 归仁 基地 ; 陆军 也 预计 邀 媒体 参访 , 最新型 的 ah - 64 e 直升机 最快 6日 就 能 在 民众 面前 亮相 。 台湾地区 向 美国 购买 30架 长 弓阿帕 契 攻击 直升机 ( ah - 64 e ) 是 前 美国总统 布什 ( george w . bush ) 政府 在 2008年 宣布 售 台 , 总金额 达 新台币 593.1亿元 ; 除了 美国 外 , 台湾 是 第2个 拥有 此 机型 的 地区 。 中新网 11月 4日 电 据 台湾 “ 中央社 ” 报道 , 台当局 防务 部门 负责人 严明 今天 ( 4日 ) 证实 台军 采购 的 最新型 阿帕契 直升机 ( ah - 64 e ) 已 抵 高雄港 。 陆军 表示 , 吊挂 顺利 , 正 进行 组装 、 地面 测试 。 严明 上午 在 台当局 “ 立法院 ” 答询 时 指出 , 首批 6架 阿帕契 直升机 ( ah - 64 e ) 已 抵 台 。 台湾 陆军 指出 , 6架 直升机 以 海运 方式 运抵 高雄港 , 上午 吊挂 上岸 作业 顺利 , 正在 进行 组装 , 组装 完 后 , 会 做 地面 测试 , 包括 开车 、 旋翼 转动 等 测试 , 相关 过程 军方 全程 保密 。 陆军 说 , 测试 结束 后 , 阿帕契 直升机 将 在 6日 或 7日 飞抵 陆军 航空 特战 指挥部 台南 归仁 基地 ; 陆军 也 预计 邀 媒体 参访 , 最新型 的 ah - 64 e 直升机 最快 6日 就 能 在 民众 面前 亮相 。 台湾地区 向 美国 购买 30架 长 弓阿帕 契 攻击 直升机 ( ah - 64 e ) 是 前 美国总统 布什 ( george w . bush ) 政府 在 2008年 宣布 售 台 , 总金额 达 新台币 593.1亿元 ; simhash的二进制表示:10110101100101110011011111001010100110000100000000000000000000001011000110010101001101111100101010011000010000000000000000000000simhash的BigInteger表示:23078054731972307805456781ns1与ns的汉明距离2
经验表明,在hash值为64位的情况下距离小于等于3表明这两篇文章相似。
- simhash应用-文章去重
- 文本去重simhash
- SimHash文档去重
- 海量数据去重之SimHash算法简介和应用
- 海量数据去重之SimHash算法简介和应用
- 海量数据去重之SimHash算法简介和应用
- 海量数据去重之SimHash算法简介和应用
- 网页去重算法Simhash
- simhash去重算法实践
- 网页去重算法simhash 简析
- 文本去重之SimHash算法
- 文本去重之SimHash算法
- 文本去重之SimHash算法
- 文本去重之SimHash算法
- 使用simhash算法对网页去重
- 文档去重算法:SimHash和MinHash
- 文档去重算法:SimHash和MinHash
- 文档去重算法:SimHash和MinHash
- java 对象数组的使用
- 关于获取各种浏览器滚动条的高度
- 快捷键 mac
- 移动Push(推送)通用类 & 原理图!
- Deep Learning(深度学习)学习笔记整理系列之(二)
- simhash应用-文章去重
- 惊呆了,开发发布一个支持web和mobile端的企业网站居然可以这么简单!
- Android MediaPlayer与Http Proxy结合之提高篇
- jdk
- spring MVC 导出excel
- do while(0) 的妙用----终于知道为什么有些人的代码中要“多此一举”了
- Deep Learning(深度学习)学习笔记整理系列之(三)
- 指定内容编码写入文件
- UVA - 11456 Trainsorting DP