谷歌如何实现网页去重?

简介: 谷歌如何实现网页去重?

你好,我是Giant。


我们每天都在使用谷歌、百度、必应等搜索引擎,高效率地查找资源信息。互联网让全世界的网民实现了内容共享。


谷歌内部的一篇文章报道,早在2008年,谷歌浏览器索引的网页数量已经达到了1万亿,每天依然在源源不断地增加。




如此海量的网页,为了避免重复检索收录,谷歌是如何对抓取的网页做去重呢?

这个问题也是一道大厂算法面试题,掌握了进大厂的概率都会增加不少哦。


一种朴素的做法是,用词向量或预训练语言模型将网页文档直接编码为固定长度的embedding,然后对于每一个新爬取的页面,和已有网页计算是否存在雷同的特征向量,或看作K=1的K近邻问题。


虽然KNN有Annoy、HNSW等高效的实现算法,但网页中往往存在大量冗余信息,如何有效将文档编码为特征向量,存在很大的难点。


刚好最近关注了局部敏感哈希算法,我发现其中的simhash非常适用于网页去重。

下面我以simhash为例,简单分享一下谷歌实现网页自动去重的原理。


网页去重的基本框架大致包含三个步骤:特征词提取、生成文档指纹、相似性计算。


特征词提取



我们可以将网页视作一篇文档。首先,从文档中提取一组能表征该文档的特征词,并计算权重,得到<特征词,权重>组成的pair二元组。


其中特征词和权重,可以通过TF-IDF等算法排序获得。TF-IDF的主要思想是,一个单词在一篇文章中出现的频率越高,且在其他文章中出现的频率越低,则该单词对当前文本的重要程度就越高,TF-IDF值就越大。


生成文档指纹



利用开源的hash函数,将每个特征词映射成为固定长度(例如64位)的二进制数,即哈希值,得到新的二元组<哈希值,权重>


随后,利用权重对产生的二进制序列进行改写,即把权重信息融入二进制序列中,变成一个实数向量。假设刚刚得到的<哈希值,权重>是<100110, 0.57>(这里哈希值是6位),那么经过改写变成了实数向量(0.57,-0.57, -0.57, 0.57, 0.57, -0.57)。


每个特征词都做了上述的改写后,对一篇文档中的所有特征词的实数向量进行累加(即对应位置相加),即可获得一个代表整个文档的实数向量。假设最后得到的实数向量是(13, 108, -22, -5, -32, 55)。


最后将上面得到的实数向量规范化,即将实数向量转换为二进制序列,转换规则为正数变为1,负数变为0。即(13, 108, -22, -5, -32, 55) --> 110001。最终得到的这个二进制序列就是本文档的文档指纹。


下图演示了文档指纹的生成过程。



文档相似性计算



计算得到每一篇文档的指纹后,需要对文档集合中的所有文档进行相似性计算,把雷同的文档过滤掉。那么,如何进行文档相似性计算呢?


对于文档A,B,其内容的相似性可以通过A,B对应的文档指纹的相似程度来体现。内容越相似,二进制序列对应位置相同的位数就越多。


两个长度相同的二进制序列之间的差异被称为“海明距离”,海明距离越小,表示两篇文档越相似。一般认为,当海明距离<=3时,两篇文档就被视为雷同。至此,问题就变成了如何求海明距离?


我们还是通过例子来说明。


假设文档A的文档指纹是100110,文档B的文档指纹是100011,显然,有两个位置上的数不一样,即海明距离为2。那么,文档A,B的海明距离具体该如何计算呢?


实际上,求海明距离,是先对两个二进制序列进行异或运算(假设运算结果是ret),再对二进制序列ret求其1的个数。所以,问题又转移至:如何求二进制序列中"1"的个数?

这又是一个经典巧妙的基础算法题!


在具体分析前,我们先来看看把一个数减1会发生什么神奇的事情?


如果一个整数不等于0,那么该整数的二进制表示中至少有一位是1。


情况1:假设这个数的二进制表示的最右边一位是1,那么经过减1操作后,最后一位变成了0而其他位不变,也就是最后一位相当于做了取反操作,由1变成0;

比如,一个二进制数1001,减1后,得到1000。


情况2:假设这个数的二进制表示的最后一位是0,而它的最右边的‘1’ 位于第m位,那么经过减1操作后,第m位由1变成0,而第m位之后的位取反,第m位之前的位保持不变。比如,一个二进制数1100,减1后,得到1011。


在这两种情况中,我们发现,把一个整数减去1,都是把它二进制数最右边的1变成0(假设最右边的 ‘1’ 位于第m位),而第m位右边若还有0,把0都变成1,第m位左边保持不变。接下来,我们把一个整数和它减去1的结果做与运算,例如:


a = 1100a-1 = 1011ret = a & (a-1) = 1000

可见,把一个整数a减去1,再和原整数a做与运算,会把该整数a最右边的1变成0,那么,一个整数的二进制序列中有多少个1就可以通过这种方式算出来(不借助 bin 等内部函数的前提下)!


以下是Python代码:


def count_of_1(num):
    cnt = 0
    while num:
        cnt += 1
        num &= num - 1
    return cnt


Simhash算法到这儿就全部介绍完了。

当然谷歌的页面去重算法还做了很多性能优化,感兴趣的同学可以看相关论文资料做深入了解哦。

相关文章
|
7月前
|
数据采集 存储 JavaScript
Buzz库网络爬虫实例:快速爬取百度搜索实时热点
Buzz库网络爬虫实例:快速爬取百度搜索实时热点
|
数据采集 搜索推荐 安全
谷歌搜索留痕快速收录怎么实现?
答案是:通过GPC爬虫池技术实现的。 在搜索引擎优化(SEO)领域,快速收录是许多网站主人追求的目标。 而在谷歌搜索引擎中,搜索留痕快速收录成为了一种重要的实现途径。 以下内容详细介绍了如何实现谷歌搜索留痕快速收录。
163 0
谷歌搜索留痕快速收录怎么实现?
|
存储 搜索推荐 NoSQL
抖音是怎么做到不重复推荐内容呢?
抖音是怎么做到不重复推荐内容呢?
|
数据采集 前端开发 Python
Python爬虫与逆向工程技术的结合,实现新闻网站动态内容的多线程抓取
Python爬虫与逆向工程技术的结合,实现新闻网站动态内容的多线程抓取
|
开发框架 算法 搜索推荐
涨知识|Google语法快速高效的搜索
涨知识|Google语法快速高效的搜索
194 0
如何实现世界排行榜功能
这应该是唯一的一篇如何在微信小游戏制作工具中实现世界排行榜功能的教程,超万字的图文教程,内容非常的详尽,能够帮助你在游戏中实现世界排行榜功能。这是一篇付费教程,但是能够帮助你节省很多很多的时间。所有的小蚂蚁的学员可以在知识拓展库中免费阅读这篇教程。
118 0
谷歌搜索留痕怎么做?有没内容限制?
因为量很大,比如我生成100万个页面,总会有几千甚至几万收录的,当然有一个前提是,你必须有自己的蜘蛛池。
502 0
谷歌搜索留痕怎么做?有没内容限制?
|
存储 负载均衡 搜索推荐
Google搜索为什么不能无限分页?
这是一个很有意思却很少有人注意的问题。 当我用Google搜索`MySQL`这个关键词的时候,Google只提供了`13`页的搜索结果,我通过修改url的分页参数试图搜索第`14`页数据,结果出现了以下的错误提示:
Google搜索为什么不能无限分页?
|
运维 搜索推荐 数据可视化
几百行代码完成百度搜索引擎,真的可以吗?(上)
Hello 大家好,我是鸭血粉丝,大家都叫我阿粉,搜索引擎想必大家一定不会默认,我们项目中经常使用的 ElasticSearch 就是一种搜索引擎,在我们的日志系统中必不可少,ELK 作为一个整体,基本上是运维标配了,另外目前的搜索引擎底层都是基于 Lucene 来实现的。
几百行代码完成百度搜索引擎,真的可以吗?(上)
|
运维 搜索推荐 数据可视化
几百行代码完成百度搜索引擎,真的可以吗?(下)
Hello 大家好,我是鸭血粉丝,大家都叫我阿粉,搜索引擎想必大家一定不会默认,我们项目中经常使用的 ElasticSearch 就是一种搜索引擎,在我们的日志系统中必不可少,ELK 作为一个整体,基本上是运维标配了,另外目前的搜索引擎底层都是基于 Lucene 来实现的。
几百行代码完成百度搜索引擎,真的可以吗?(下)