整体系统介绍搜索引擎可以分为四个部分:搜集、分析、索引、查询。
* 搜集:就是利用爬虫爬取网页
* 分析:主要负责网页内容抽取、分词,构建临时索引,计算 PageRank 值这几部分工作
* 索引:主要负责通过分析阶段得到的临时索引,构建倒排索引
* 查询:主要负责响应用户的请求,根据倒排索引获取相关网页,计算网页排名,返回查询结果给用户
搜集
* 搜索引擎把整个互联网看作数据结构中的有向图,把每个页面看作一个顶点。如果某个页面中包含另外一个页面的链接,就在两个顶点之间连一条有向边。可以利用图的遍历搜索算法,来遍历整个互联网中的网页。
* 搜索引擎采用的是广度优先搜索策略。
* 权重比较高的链接,作为种子网页链接,放入到队列中
* 爬虫按照广度优先的策略,不停地从队列中取出链接,取爬取对应的网页,解析出网页里包含的其他网页链接,再将解析出来的链接添加到队列中。
1. 待爬取网页链接文件:links.bin
* 在爬取页面的过程中,爬虫会不停地解析页面链接,将其放到队列中
* 队列中的链接存储在磁盘中的文件(links.bin)。爬虫从 links.bin 文件中,取出链接去爬取对应的页面。等爬取到网页之后,将解析出来的链接,直接存储到 links.bin 文件中。
* 文件来存储支持断点续爬
2. 网页判重文件:bloom_filter.bin
* 使用布隆过滤器,可以快速且非常节省内存地实现网页的判重,避免重复爬取相同的网页
* 要定期地将布隆过滤器持久化存储到磁盘bloom_filter.bin 文件中,避免机器重启后,布隆过滤器被清空
* 当机器重启之后,重新读取磁盘中的 bloom_filter.bin 文件,将其恢复到内存中
3. 原始网页存储文件:doc_raw.bin
* 爬取到网页之后,需要将其存储下来,以备后面离线分析、索引之用
* 把多个网页存储在一个文件中,每个网页之间,通过一定的标识进行分隔,方便后续读取
* 每个文件的大小不能超过一定的值(比如 1GB),因为文件系统对文件的大小也有限制。
4. 网页链接及其编号的对应文件:doc_id.bin
* 网页编号是给每个网页分配一个唯一的 ID,方便后续对网页进行分析、索引
* 每爬取到一个网页之后,就从一个中心的计数器中拿一个号码,分配给这个网页
* 在存储网页的同时,将网页链接跟编号之间的对应关系,存储在一个 doc_id.bin 文件中
分析
分析阶段两个步骤(1)抽取网页文本信息,(2)分词并创建临时索引
1. 抽取网页文本信息
* 网页是半结构化数据,要从半结构化的网页中,抽取出搜索引擎关系的文本信息
这个抽取的过程分为两步
(1)去掉 JavaScript 代码、CSS 格式以及下拉框中的内容
* 利用 AC 自动机这种多模式串匹配算法将<style>, <script>, <option>标签包裹的字符删除
(2)去掉所有 HTML 标签,这过程跟第一步类似
2. 分词并创建临时索引
* 从网页中抽取出了文本信息,要对文本信息进行分词,并且创建临时索引
* 中文分词比较复杂太多了,可以基于字典和规则的分词方法
字典也叫词库,里面包含大量常用的词语。借助词库并采用最长匹配规则,来对文本进行分词。所谓最长匹配,也就是匹配尽可能长的词语。
* 具体到实现层面,将词库中的单词,构建成 Trie 树结构,然后拿网页文本在 Trie 树中匹配
* 网页的文本信息在分词完成后,得到一组单词列表。把单词与网页之间的对应关系,写入到一个临时索引文件中(tmp_Index.bin),这个临时索引文件用来构建倒排索引文件
*临时索引文件中存储的是单词编号,这样做是为了节省存储的空间。给单词编号的方式,跟给网页编号类似
*这个过程中使用散列表记录已经编过号的单词。对分词的先到散列表中查找,如果找到那就直接使用;如果没有找到,再去计数器中拿号码,并将这个新单词以及编号添加到散列表中
当所有的网页处理(分词及写入临时索引)完成之后,再将单词跟编号之间的对应关系写入到磁盘文件中,并命名为 term_id.bin
索引
索引阶段主要负责将分析阶段产生的临时索引,构建成倒排索引
倒排索引( Inverted index)中记录了每个单词以及包含它的网页列表
那如何通过临时索引文件,构建出倒排索引文件?
考虑到临时索引文件很大,无法一次性加载到内存中,搜索引擎一般会选择使用多路归并排序的方法来实现
先对临时索引文件,按照单词编号的大小进行排序
因为临时索引很大,可以用归并排序的处理思想,将其分割成多个小文件,先对每个小文件独立排序,最后再合并在一起
展开