搜索引擎背后的数据结构和算法

文章目录

    • 1. 整体系统介绍
    • 2. 搜集
      • 2.1 待爬取网页链接文件:links.bin
      • 2.2 网页判重文件:bloom_filter.bin
      • 2.3 原始网页存储文件:doc_raw.bin
      • 2.4 网页链接及其编号的对应文件:doc_id.bin
    • 3. 分析
      • 3.1 抽取网页文本信息
      • 3.2 分词并创建临时索引
    • 4. 索引
    • 5. 查询
    • 6. 总结

搜索引擎实现起来,技术难度非常大,技术的好坏直接决定了产品的核心竞争力。
搜索引擎的设计与实现中,会用到大量的算法。百度、Google 这样的搜索引擎公司,面试时,会格外重视考察候选人的算法能力。

1. 整体系统介绍

以下介绍,如何在一台机器上(假设内存是8GB,硬盘是100多GB),通过少量的代码,实现一个小型搜索引擎。

搜索引擎大致分为四个部分:搜集分析索引查询

  • 搜集,就是利用爬虫爬取网页。
  • 分析,主要负责网页内容抽取、分词,构建临时索引,计算PageRank值。
  • 索引,主要负责通过分析阶段得到的临时索引,构建倒排索引。
  • 查询,主要负责响应用户的请求,根据倒排索引获取相关网页,计算网页排名,返回查询结果给用户。

2. 搜集

互联网越来越发达,网站越来越多,对应网页也越来越多。对于搜索引擎来说,它事先并不知道网页都在哪里。那搜索引擎是如何爬取网页的呢?

搜索引擎把整个互联网看作 有向图,把每个页面看作一个顶点。如果某个页面中包含另外一个页面的链接,就在两个顶点之间连一条有向边。利用图的遍历搜索算法,来遍历整个互联网中的网页。

  • 搜索引擎采用的是广度优先搜索策略。具体点讲的话,先找一些比较知名的网页(权重比较高)的链接(比如新浪主页、腾讯主页),作为种子网页链接,放入到队列中。爬虫按照广度优先的策略,不停地从队列中取出链接,然后爬取对应的网页,解析出网页里包含的其他网页链接,再将解析出来的链接添加到队列中。

2.1 待爬取网页链接文件:links.bin

广度优先搜索爬取页面过程中,爬虫会不停地解析页面链接,将其放到队列中。于是,队列中的链接会越来越多,可能多到内存放不下。所以,用一个存储在磁盘中的文件(links.bin)来作为广度优先搜索中的队列。爬虫从links.bin文件中,取出链接去爬取对应的页面。等爬取到网页之后,将解析出来的链接,直接存储到links.bin文件中。这样用文件来存储网页链接的方式,还有其他好处。比如,支持断点续爬。当机器断电之后,网页链接不会丢失;重启之后,还可以从之前爬取到的位置继续爬取。

如何解析页面获取链接,可以把整个页面看作一个大的字符串,利用字符串匹配算法,搜索这样一个网页标签,然后顺序读取之间的字符串,就是网页链接。

2.2 网页判重文件:bloom_filter.bin

如何避免重复爬取相同的网页呢?使用布隆过滤器,就可以快速并且非常节省内存地实现网页的判重。

如果把布隆过滤器存储在内存中,宕机重启后,布隆过滤器就被清空了。可能导致大量已经爬取的网页会被重复爬取。

我们可以定期地(比如每隔半小时)将布隆过滤器持久化到磁盘中,存储在bloom filter.bin文件中。即便出现机器宕机,也只会丢失布隆过滤器中的部分数据。当机器重启后,就可以重新读取磁盘中的bloom_filter.bin文件,将其恢复到内存中。

2.3 原始网页存储文件:doc_raw.bin

爬取到网页后,需要将其存储下来,以备后面离线分析、索引之用。如何存储海量的原始网页呢?

如果把每个网页都存储为一个独立的文件,那磁盘中的文件会非常多。常用的文件系统显然不适合存储如此多的文件。所以,可以把多个网页存储在一个文件中。每个网页之间,通过标识进行分隔,方便后续读取。具体的存储格式,如图所示。其中,doc_id这个字段是网页的编号。
在这里插入图片描述
这样的一个文件也不能太大,因为文件系统对文件的大小也有限制。所以,我们可以设置每个文件的大小上限(比如1GB)。随着越来越多的网页被添加到文件中,文件越来越大,当超过1GB的时候,就创建一个新文件,用来存储新爬取的网页。

假设机器的硬盘大小是100GB左右,一个网页的平均大小是64KB。那在一台机器上,我们可以存储100万到200万左右的网页。假设机器的带宽是10MB,那下载100GB的网页,大约要10000秒。也就是说,爬取100多万的网页,只需要花费几小时的时间。

2.4 网页链接及其编号的对应文件:doc_id.bin

网页编号就是给每个网页分配一个唯一的ID,方便后续对网页分析、索引。那如何给网页编号呢?

  • 可以按照网页被爬取的先后顺序,从小到大依次编号。具体是这样做的:维护一个中心的计数器,每爬取到一个网页,就从计数器中拿一个号码,分配给这个网页,然后计数器加一。存储网页的同时,将网页链接编号之间的对应关系,存储在另一个doc_id.bin文件中。

爬取网页的过程中,涉及的四个重要的文件,links.bin 和 bloom filter.bin 这两个文件是爬虫自身所用的。另外两个(doc raw.bin、doc id.bin)是作为搜集阶段的成果,供后面的分析、索引、查询用。

3. 分析

网页爬下来后,需要对网页进行离线分析。主要包括两个步骤,1. 抽取网页文本信息,2. 分词并创建临时索引。

3.1 抽取网页文本信息

网页是半结构化数据,里面夹杂着各种标签、JavaScript代码、CSS样式。搜索引擎只关心网页中的文本信息,我们依靠HTML标签来抽取网页中的文本信息,大体可以分为两步。

  • 第一步是去掉JavaScript代码、CSS格式以及下拉框中的内容(因为下拉框在用户不操作的情况下,也是看不到的)。也就是<style></style>,<script></script>,<option></option>这三组标签之间的内容。可以利用AC自动机这种多模式串匹配算法,一次性查找<style>,<script>,<option>这三个关键词。当找到某个关键词出现的位置之后,只需要依次往后遍历,直到对应结束标签(</style>,</script>,</option>)为止。这期间遍历到的字符串连带着标签就应该从网页中删除。
  • 第二步是去掉所有HTML标签。也是通过字符串匹配算法来实现的。

3.2 分词并创建临时索引

经过上面的处理,我们就从网页中抽取出了我们关心的文本信息。接下来,要对文本信息进行分词,并且创建临时索引。

  • 对英文网页来说,分词非常简单。只需要通过空格、标点符号等分隔符,将每个单词分割开来就可以了。
  • 对于中文来说,分词就复杂太多了。介绍一种比较简单的思路,基于字典和规则的分词方法。

字典也叫词库,里面包含大量常用的词语。借助词库并采用最长匹配规则,来对文本进行分词。所谓最长匹配,也就是匹配尽可能长的词语。具体到实现层面,我们可以将词库中的单词,构建成Trie树结构,然后拿网页文本在Trie 树中匹配。

每个网页的文本信息在分词完成后,都得到一组单词列表。把单词与网页之间的对应关系,写入到一个临时索引文件中(tmp_Index.bin),这个临时索引文件用来构建倒排索引文件。临时索引文件的格式如下:
在这里插入图片描述
在临时索引文件中,我们存储的是单词编号term_id,而非单词本身。这样做的目的主要是为了节省存储空间。这些单词的编号是怎么来的呢?

给单词编号的方式,跟给网页编号类似。维护一个计数器,每当从网页文本信息中分割出一个新单词的时候,就从计数器中取一个编号,分配给它,然后计数器加一。

在这个过程中,我们还需要使用散列表,记录已经编过号的单词。在对网页文本信息分词的过程中,我们拿分割出来的单词,先到散列表中查找,如果找到,那就直接使用已有的编号;如果没有找到,再去计数器中拿号码,并且将这个新单词以及编号添加到散列表中。

当所有的网页处理(分词及写入临时索引)完成之后,再将这个单词跟编号之间的对应关系,写入到磁盘文件中,并命名为term_id.bin。

经过分析阶段,得到了两个重要的文件。它们分别是临时索引文件(tmpindex.bin)和单词编号文件(term_id.bin)。

4. 索引

索引主要负责将分析阶段产生的临时索引,构建成倒排索引。倒排索引(Inverted index)中记录了每个单词以及包含它的网页列表。
在这里插入图片描述
如何通过临时索引文件,构建出倒排索引文件呢?

考虑到临时索引文件很大,无法一次加载到内存,搜索引擎一般会选择使用多路归并排序的方法来实现。

  • 先对临时索引文件,按照单词编号的大小排序。因为临时索引很大,所以一般基于内存的排序算法就没法处理这个问题。可以用归并排序的处理思想,将其分割成多个小文件,先对每个小文件独立排序,最后再合并在一起。实际的软件开发中,可以直接利用MapReduce来处理。
  • 临时索引文件排序完成之后,相同的单词就被排列到了一起。只需顺序地遍历排好序的临时索引,就能将每个单词对应的网页编号列表找出来,然后把它们存储在倒排索引文件中。如图。
    在这里插入图片描述
    除了倒排文件之外,我们还需要一个文件,来记录每个单词编号在倒排索引文件中的偏移位置。把这个文件命名为term_offset.bin。这个文件的作用是,帮助我们快速地查找某个单词编号在倒排索引中存储的位置,进而快速地从倒排索引中读取单词编号对应的网页编号列表。
    在这里插入图片描述
    经过索引阶段的处理,我们得到倒排索引文件(index.bin)和记录单词编号在索引文件中的偏移位置的文件(term_ofset.bin)。

5. 查询

前面三个阶段的处理,只是为了最后的查询做铺垫。

  • doc_id.bin:记录网页链接和编号之间的对应关系。
  • term_id.bin:记录单词和编号之间的对应关系。
  • index.bin:倒排索引文件,记录每个单词编号以及对应包含它的网页编号列表
  • term_offsert.bin:记录每个单词编号在倒排索引文件中的偏移位置。

除了倒排索引文件(index.bin)比较大之外,其他的都比较小。为了方便快速查找数据,将其他三个文件都加载到内存中,并且组织成散列表这种数据结构。

当用户在搜索框中,输入某个查询文本的时候,先对用户输入的文本进行分词处理。假设分词之后,得到k个单词。

拿这k个单词,去term_id.bin对应的散列表中,查找对应的单词编号。经过这个查询之后,得到了这k个单词对应的单词编号。

拿这k个单词编号,去term_offset.bin对应的散列表中,查找每个单词编号在倒排索引文件中的偏移位置。得到了k个偏移位置。

拿这k个偏移位置,去倒排索引(index.bin)中,查找k个单词对应的包含它的网页编号列表。得到了k个网页编号列表。

针对这k个网页编号列表,统计每个网页编号出现的次数。我们可以借助散列表来进行统计。统计得到的结果,我们按照出现次数的多少,从小到大排序。出现次数越多,说明包含越多的用户查询单词(用户输入的搜索文本,经过分词之后的单词)。

经过一系列查询,就得到了一组排好序的网页编号。拿着网页编号,去doc_id.bin文件中查找对应的网页链接,分页显示给用户就可以了。

6. 总结

以上只是一个搜索引擎设计的基本原理,有很多优化、细节并未涉及,如计算网页权重的 PageRank 算法、计算查询结果排名的 tf-idf 模型等等。

涉及的数据结构和算法有:图、散列表、Trie树、布隆过滤器、单模式字符串匹配算法、AC自动机、广度优先遍历、归并排序等。

如果有时间,自己写代码实现一个简单的搜索引擎。即便只是一个demo,但对于深入理解数据结构和算法是很有帮助的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文浅尝 | DKN: 面向新闻推荐的深度知识感知网络

笔记整理&#xff1a;仲亮靓&#xff0c;东南大学硕士研究生&#xff0c;研究方向是基于知识图谱的推荐系统动机新闻文本的语言非常凝练&#xff0c;其中包含了很多实体和常识知识。但目前的新闻个性化推荐方法都没有利用这些外部知识&#xff0c;也没有使用新闻之间潜在的知识…

聊聊工业界做机器学习的里程碑

文 | 吴海波编 | YY阅读说明&#xff0c;本文的机器学习领域限制于互联网搜索、推荐、广告场景&#xff0c;仅限于个人观点。2017年&#xff0c;我和团队的几个核心去了趟北京&#xff0c;找了各大互联网公司一线实战的同学&#xff0c;交流各自在机器学习上的经验。这次交流让…

直通BAT JVM必考题:Minor GC、Major GC、Full GC的区别

Java面试过程&#xff0c;JVM属于必考题系列&#xff1a; 直通BAT必考题系列&#xff1a;深入详解JVM内存模型与JVM参数详细配置 直通BAT必考题系列&#xff1a;JVM的4种垃圾回收算法、垃圾回收机制与总结 直通BAT必考题系列&#xff1a;7种JVM垃圾收集器特点&#xff0c;优…

matplotlib绘制多张图、多子图、多例图

绘制多图 关键&#xff1a; fig plt.figure(1) 表示新建第几个图 import matplotlib.pyplot as pltfig plt.figure(1) plt_rec_loss [1,2,3,4,5,6] plt_rec_recall [4,3,6,5,8,9] plt.xlabel("epoch") plt.ylabel("loss") plt.plot(range(len(plt_re…

jieba分词并做分析

Github&#xff1a;结巴分词地址 https://github.com/fxsjy/jieba 几种分词方法的简单使用&#xff1a;一 . jieba安装、示例 pip install jieba&#xff0c;jieba分词的语料是基于人民日报。分词示例1 import jieba 2 3 str1 江州市长江大桥 4 word_object jieba.cut(s…

研讨会 | CCF TF 第 17 期:认知计算产业化落地

CCF TF 技术前线只为技术专家CCFTF第17期主题 认知计算产业化落地2019年05月11日上海斯波特酒店五楼&#xff08;上海市南丹路15号&#xff0c;徐汇区政府对面&#xff09;人类迈入人工智能时代&#xff0c;技术的发展使得机器可以从大数据中提取信息&#xff0c;串联成知识&a…

短网址系统

文章目录1. 短网址服务整体介绍2. 如何通过哈希算法生成短网址&#xff1f;2.1 如何让短网址更短2.2 如何解决哈希冲突&#xff1f;2.3 如何优化哈希算法生成短网址的性能&#xff1f;3. 如何通过ID生成器生成短网址&#xff1f;3.1 相同的原始网址可能会对应不同的短网址3.2 如…

一个神经元的价值和一个神经病的坚持

作者 | 周博磊来源 | 机器之心一个神经元能够催生多少故事&#xff1f;香港中文大学信息工程系助理教授周博磊近日撰文介绍了他自 2015 年开始至今对神经元的研究经历。最近&#xff0c;他与 David Bau、朱俊彦等人合作的神经元研究论文发表在了 PNAS 杂志上。以下是周博磊的原…

直通BAT必考题系列:深入剖析JVM之G1收集器、及回收流程、与推荐用例

金三银四马上到了&#xff0c;即将进入面试的高峰期。在BAT面试中&#xff0c;JVM基本都是必考的系列。你至少需要掌握JVM内存模型与JVM参数详细配置&#xff0c;JVM的4种垃圾回收算法、垃圾回收机制与总结&#xff0c;以及今天重点谈到的JVM垃圾回收算法的实现&#xff1a;JVM…

多任务学习方法

最近一直在做多任务&#xff0c;但是效果好象没什么提升&#xff0c;因为都是凭自己的想法和感觉在做。于是上网查找了一些这方面的资料&#xff0c;寻求一些理论上的支撑和前人经验上的帮助。 多任务学习&#xff1a; 故名思意&#xff0c;就是多个任务一起学习。为什么要进行…

曹羽 | 从知识工程到知识图谱全面回顾

本文转载自公众号&#xff1a;集智俱乐部。文本挖掘和图形数据库 | ©ontotext导语知识工程是符号主义人工智能的典型代表&#xff0c;近年来越来越火的知识图谱&#xff0c;就是新一代的知识工程技术。知识工程将如何影响未来人工智能领域的发展&#xff0c;甚至让计算机拥…

4大JVM性能分析工具详解,及内存泄漏分析方案

谈到性能优化分析一般会涉及到&#xff1a; Java代码层面的&#xff0c;典型的循环嵌套等 还会涉及到Java JVM&#xff1a;内存泄漏溢出等 MySQL数据库优化&#xff1a;分库分表、慢查询、长事务的优化等 阿里P8架构师谈&#xff1a;MySQL慢查询优化、索引优化、以及表等优化…

从 0 搭建一个工业级推荐系统

推荐系统从来没像现在这样&#xff0c;影响着我们的生活。当你上网购物时&#xff0c;天猫、京东会为你推荐商品&#xff1b;想了解资讯&#xff0c;头条、知乎会为你准备感兴趣的新闻和知识&#xff1b;想消遣放松&#xff0c;抖音、快手会为你奉上让你欲罢不能的短视频。而驱…

论文浅尝 | 虚拟知识图谱:软件系统和应用案例综述

本文转载自公众号&#xff1a;DI数据智能。Virtual Knowledge Graphs: An Overview of Systems and Use Cases作者&#xff1a;Guohui Xiao, Linfang Ding, Benjamin Cogrel & Diego Calvanese供稿&#xff1a;Guohui Xiao编者按&#xff1a;Data Intelligence 发表意大利博…

LeetCode 169. 求众数(摩尔投票)

文章目录1. 题目信息2. 解题思路3. 代码3.1 排序3.2 map计数3.3 摩尔投票1. 题目信息 给定一个大小为 n 的数组&#xff0c;找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在众数。 示例 1:输入…

阿里P8架构师谈:JVM的内存分配、运行原理、回收算法机制

不管是BAT面试&#xff0c;还是工作实践中的JVM调优以及参数设置&#xff0c;或者内存溢出检测等&#xff0c;都需要涉及到Java虚拟机的内存模型、内存分配&#xff0c;以及回收算法机制等&#xff0c;这些都是必考、必会技能。 JVM内存模型 JVM内存模型可以分为两个部分&…

我的BERT!改改字典,让BERT安全提速不掉分(已开源)

文 | 苏剑林编 | 小轶背景当前&#xff0c;大部分中文预训练模型都是以字为基本单位的&#xff0c;也就是说中文语句会被拆分为一个个字。中文也有一些多粒度的语言模型&#xff0c;比如创新工场的ZEN和字节跳动的AMBERT&#xff0c;但这类模型的基本单位还是字&#xff0c;只不…

2020年考证时间表汇总!这些证书值得拥有!

原文地址&#xff1a; https://zhuanlan.zhihu.com/p/100824416 2020年考证时间表汇总&#xff01;这些证书值得拥有&#xff01;已认证的官方帐号154 人赞同了该文章昨日之日不可留&#xff0c;2019年已然过去&#xff0c;2020年的我们不能再一成不变&#xff01;快根据自身情…

征稿 | 2019年全国知识图谱与语义计算大会(CCKS2019)第二轮征稿启事

2019年全国知识图谱与语义计算大会China Conference on Knowledge Graph and Semantic Computing (CCKS 2019)2019年8月24日-27日&#xff0c;杭州征稿截止: 2019年5月18日全国知识图谱与语义计算大会&#xff08;CCKS: China Conference on Knowledge Graph and Semantic Comp…

直通BAT必考题系列:JVM的4种垃圾回收算法、垃圾回收机制与总结

BAT必考JVM系列专题 直通BAT必考题系列&#xff1a;深入详解JVM内存模型与JVM参数详细配置 垃圾回收算法 1.标记清除 标记-清除算法将垃圾回收分为两个阶段&#xff1a;标记阶段和清除阶段。 在标记阶段首先通过根节点&#xff08;GC Roots&#xff09;&#xff0c;标记所…