第2章介绍了搜索客户端研发所需的基础技术,基于这些技术可设计并实现搜索客户端的不同功能。客户端作为搜索服务的延伸,依赖服务端实现信息检索功能,这同时也需要其他服务端的支持。客户端与服务端的紧密合作,确保了搜索业务的完整性。本章将探讨服务端与客户端协同的基础服务,重点介绍搜索服务的核心能力,以及客户端在提升搜索服务价值方面的重要性。
搜索客户端依赖的服务包括两部分:一部分是客户端运行时与服务端对接的服务,另一部分是搜索业务与服务端对接的服务。
客户端运行时对接的服务端常见的有云控服务端和数据服务端,服务端是客户端实现基础能力的保障,为客户端中的功能提供数据同步支持。本节的内容与搜索服务无依赖关系,既适用于搜索客户端,也适用于其他产品客户端。
1.云控服务端的对接
云控服务端通常是客户端类产品依赖的核心服务,用来下发客户端依赖的数据,包含客户端中不同业务的配置。在客户端中,与云控服务端对接的相关能力通常被封装为一个独立的云控模块。云控模块主要分为 调度控制、状态收集、数据传输 及 数据分发 这四个核心子模块,如图3-1所示。
图3-1 云控模块与云控服务端及业务模块的通信
云控功能的触发要通过规则或特定的事件,所以需要在客户端明确更新的时机,即通过客户端云控模块向云控服务端发送更新最新配置状态的网络请求,这部分工作主要由调度控制子模块负责。
当 调度控制子模块 确定需要与云控服务端同步数据时,先会收集当前设备中的配置项、开关等数据,再将这些数据提交到云控服务端。由于业务功能不同,传输的数据不同,业务中的数据格式也有所不同,由 状态收集子模块 负责获取每个业务当前的数据状态, 状态收集子模块 与业务模块是一对多的关系。数据收集完成后,由数据传输子模块对数据进行打包,调用网络模块传输数据至云控服务端,等待接收云控服务端返回的数据。之后通过数据分发子模块将不同的数据分发给不同的业务,至此基本的云控数据更新流程完成。
云控模块与云控服务端的通信是基于C/S(Client/Server,客户端/服务器)架构实现的。通信请求通常在客户端的启动阶段、某个时间周期或由某个事件触发,以实现客户端配置项数据及其状态的上报和更新任务。云控更新过程中更新的是多个业务的数据,随着团队规模变大,会涉及多个模块,也会涉及多个子团队,从架构设计的角度看,业务数据的拼装及解析工作应该交给业务层来管理,这样既可以避免业务升级带来的信息不同步或其他数据解析问题,同时还可以让云控模块处于长期稳定的状态。
2.数据服务端的对接
数据服务端为客户端提供数据存储支持,记录与业务或用户行为相关的数据。在客户端将与数据服务端对接的相关能力封装为独立的数据收集模块,以支持不同业务记录相关指标的数据项。
数据收集模块与数据服务端基于C/S架构通信,以上行数据为主。关于数据收集能力的建设参见8.3.2节。
搜索业务与服务端对接的服务主要为搜索业务构建。按照是否可定制将搜索业务对接的服务端分为自有服务端和第三方服务端两种,其中自有服务端又分为搜索服务前端和自建内容服务端,第三方页面或站点相关的服务都属于第三方服务端。
1.搜索服务前端的对接
搜索引擎是一个比较庞大的系统,在这个系统中,通常以网页的形式为用户提供内容检索服务。在PC时代,搜索产品没有客户端,用户可以使用浏览器直接加载搜索引擎主页来使用搜索服务。
搜索服务端提供内容检索的能力,在搜索客户端中用户输入搜索关键字,客户端通过浏览内核加载携带搜索关键字的URL,为用户展示搜索结果。搜索客户端对接的是搜索服务前端,前端通常指的是网站或应用程序的用户界面部分,在搜索服务中前端主要是运行于PC端、移动端等浏览器(或搜索客户端)上展示给用户的网页。
在早期,搜索客户端与搜索前端的通信是基于B/S(Browser/Server,浏览器/服务器)架构实现的,客户端可以通过浏览内核加载搜索引擎主页并使用搜索服务。
随着客户端与服务端协同的不断发展,现在搜索客户端与搜索前端已经可以按需基于C/S和B/S的混合结构进行通信了。搜索服务的更多内容在本章后面会有更详细的介绍,这里不再展开。关于客户端的设计,应该重点关注网页与客户端的通信,以及端云协同实现的差异化(参见第5章),并且要尽量保证结果页加载及控制逻辑的独立性。
2.自建内容服务端的对接
搜索客户端浏览的自建内容(比如视频、地图、图片等),通常存放在自有服务器中为搜索提供服务。
在浏览器中使用搜索服务,搜索结果及落地页只能是网页格式,否则就会出现内容可被搜索到但无法打开的情况。而在搜索客户端的支持下,可以对自建内容的格式进行定制化支持,一些非网页格式的自建内容,可以被搜索到,也可以在搜索客户端中展现及交互。
因为是自有服务,搜索客户端与自建内容服务端的通信既可基于C/S架构实现,也可基于B/S架构实现。从内容的可用性来看,自建内容服务端应可根据客户端的信号参数,以不同的架构模式提供服务。在客户端的架构设计中,应重点关注内容的可扩展性,这部分内容在本书的第6章介绍。
3.第三方站点服务端的对接
搜索客户端与第三方站点服务端的对接同样是前端,主要用来加载落地页,通常是用户浏览搜索结果时,点击结果页内链接跳转至落地页。第三方站点与搜索客户端定向协同的机会不多,二者通信主要基于B/S架构。搜索结果中的第三方内容主要为网页,依赖搜索客户端的浏览内核加载、展现及交互,以支持用户查看页面内容。
搜索客户端除了需要具备基础的页面浏览能力外,还需要具备一些辅助功能来为用户浏览提供更好的体验。值得一提的是,落地页的浏览体验是整个搜索体验中的一个重要环节。
需要提醒的是,第三方的服务和内容存在不可控的情况,其服务质量、稳定性、安全性都需要重点关注,并需要构建相应的机制及管控策略,以此来保证用户在使用搜索客户端时不会产生异常。这部分的内容在本书的第7章介绍。
本节主要介绍搜索服务的基本架构。从客户端的角度来看,搜索服务是个黑盒。客户端在发起搜索请求时,会通过URL携带搜索关键字给服务端。服务端在收到客户端的请求后,解析对应的搜索关键字信息,从搜索引擎的数据库中,检索出相关的结果并以网页的格式呈现给用户。在这个过程中,客户端研发人员不需要关注服务端如何运转,就可以实现基本的客户端搜索能力,但有关端云协同的事项,客户端研发人员就较难提出关键的建议。
搜索业务的本质,就是信息的整合,即从海量的数据中找到用户想要的内容。基于这个思路,搜索引擎至少需要解决3个问题。
❑ 内容如何产生。 有内容,搜索引擎才可以实现对内容的检索,没有内容,搜索就会缺少受体,自然检索不出结果。即便有了内容,也需要在收集的过程中考虑其质量和时效性,比如过多的重复内容,会使用户的搜索体验变差,重复内容对服务器的存储及计算来说也是一种资源浪费。
❑ 海量的内容存储和检索问题。 搜索引擎存储的内容越多,可检索到的结果就会越多,相应地,检索过程需要处理的信息量就会增大,检索的效率就会降低。数据入库的方案一般会与检索的方案相关。如何入库及存储内容以实现高效检索也是搜索引擎需要考虑的关键问题,否则在愈发海量的数据面前,检索的效率会变得越来越低,用户的需求长期得不到满足,搜索体验就会变得极差。
❑ 如何理解用户搜索需求及结果内容匹配。 用户输入搜索关键字,搜索引擎如何理解用户的需求,并从海量的数据中找到匹配的结果,这些问题需要有对应的机制和策略来实现低成本的优化。这与搜索引擎的匹配策略有关,也与产品策略有关,同样也受搜索引擎数据库中的数据影响。
上述内容仅是笔者个人的理解,与实际中遇到的问题可能有一定偏差,但“万变不离其宗”,搜索引擎需要解决的问题都与这3个问题有密切的关系。
用户使用搜索引擎时,希望检索到的就是整个互联网中的内容,也就是说,希望从整个互联网范围检索想要的内容。基于这个需求,互联网中产生的内容应该尽可能地被搜索引擎收录。在搜索引擎中,网页的收录工作主要由网页爬虫来完成。网页爬虫技术是一个公开已久的技术。
搜索引擎有3个最主要的指标——全、快、准。在用户检索阶段,快和准是核心指标;在内容收集阶段,全和快是核心指标。这就要求网页爬虫既能覆盖较广的内容,又能快速抓取时效性较高的内容,因此,爬虫的设计及应用是非常关键的。
网页爬虫抓取网页的思路可以概括为:首先加载主页面,保存页面数据,然后通过主页面中的链接抓取子页面,递归地进行下去,以获取更多的页面内容。图3-2所示是基本爬虫框架及工作流程,其详细的流程说明如下。
1)首先从互联网页面中选择一部分网页,以这些网页的地址作为种子URL并将它们存储在种子URL队列中,网页爬虫再将种子URL队列中的这些种子URL放入待抓取URL队列中。
2)网页爬虫从待抓取URL队列中依次读取URL。
3)网页爬虫将URL交给网页下载器。
4)网页下载器完成网页内容的下载。
5)网页爬虫提取网页中的内容,包括网页的源码信息。这个过程中会做两件事:
a)将网页中的内容存储到已抓取网页库中,等待建立索引等后续处理;
b)将网页的URL放入已抓取URL队列中,以避免网页的重复抓取。
6)从刚下载的网页中提取出所包含的链接信息——sURLs。
图3-2 基本的爬虫框架及工作流程
7)获取已抓取URL队列中的数据信息——hURLs。
8)sURLs和hURLs进行匹配,将没有被抓取过的URL,放入待抓取URL队列末尾,在之后的抓取调度中会下载这个URL对应的网页。
重复上面的流程,直到待抓取URL队列为空,这意味着爬虫系统已经将能抓取的网页全部抓完,即完成了一轮抓取。抓取策略可以分为3种:全量抓取、增量抓取和实时定向抓取。将这3种策略组合应用于不同的场景,可以尽可能多地覆盖不同类型的网页,并抓取到时效性较高的内容。
❑ 全量抓取: 搜索引擎爬虫的基本能力,目标是覆盖大部分站点及页面,配置的种子URL较多;特点为抓取的网页较全,任务较重,一次完整的抓取工作完成迭代周期比较长,抓取的内容时效性偏弱。
❑ 增量抓取: 针对全量抓取内容时效性偏弱问题的解决方案,它可以使用更小的任务量和迭代周期对时效性较高的站点或页面进行内容抓取,种子URL只需要配置几个重点关注的站点或页面,就可以实现较小的时间间隔抓取到新的内容;常见的增量抓取包括对专题页面或对新闻门户等站点的抓取。
❑ 实时定向抓取: 全量抓取和增量抓取都是网页爬虫主动按照规则周期性抓取网页内容,当页面内容是自有内容或由合作伙伴产生时,可以建立实时定向抓取机制,即当有新内容产生或内容有变化时,由内容提供方通知网页爬虫抓取新内容,或按照搜索引擎的标准将新增的内容入库,实现内容的实时更新。
在将网页收录到已抓取网页库的过程中,由于抓取时间与网页产生的时间存在一定的时间差。当一次抓取完成后,也会存在一些页面的内容没有被收录的情况。同时,页面被抓取之后其内容还有可能产生变化。这些情况下要保证检索的内容有较高的时效性,需要定向优化爬虫的更新机制,以符合搜索服务的业务目标。
据统计,相似的网页数量占总网页数量的比例高达29%,而完全相同的网页占总网页数量的比例大约为22%,二者相加,即互联网中有一半以上的网页是完全相同或者相近的(数据来自《这就是搜索引擎》一书)。识别重复网页一直是搜索引擎的关键能力之一,这项能力的强弱决定了后续存储、计算的成本及检索的质量,也间接影响着解决搜索引擎“准”的问题。针对内容的去重问题,本节重点介绍重复网页的不同类型、识别价值、思路及算法。
1.重复网页的不同类型
这些重复的网页中,有的是没有一点儿改动的副本,有的是仅在内容上稍做修改,有的则是页面布局不同。按照内容和布局的区别,重复网页可以归结为以下4种类型。
❑ 完全重复页面: 如果两个页面的内容和布局格式毫无差别,则称这种页面为完全重复页面。
❑ 内容重复页面: 如果两个页面的内容相同,但是布局格式不同,则称这种页面为内容重复页面。
❑ 布局重复页面: 如果两个页面有部分重要的内容相同,并且布局格式相同,则称这种页面为布局重复页面。
❑ 部分重复页面: 如果两个页面有部分重要的内容相同,但是布局格式不同,则称这种页面为部分重复页面。
所谓“近似重复网页发现”,就是通过技术手段快速全面发现这些重复信息。快速准确地发现这些相似的网页已经成为提高搜索引擎服务质量的关键技术之一。
2.重复网页识别对搜索引擎的价值
识别完全相同或者近似重复网页对搜索引擎有很多价值。
❑ 节省存储空间。 如果系统能够找出这些重复网页并将它们从自有数据库中去掉,就能够节省部分存储空间,进而可以利用这部分空间存放更多的有效网页内容。同时因为重复项的减少,也提升了搜索引擎的搜索质量和用户的搜索体验。
❑ 提升抓取效率。 如果系统能够通过对以往信息的分析,提前发现重复网页,在以后的网页抓取过程中就可以避开这些重复网页,从而提高网页的抓取效率。如某个站点的内容原创度不足,则可以忽略对其站点的抓取。
❑ 辅助计算权重。 如果某个网页被镜像的次数较多,说明该网页的内容相对重要且受欢迎。如果一个站点中的大部分网页内容都比较重要,那么在抓取网页时,应给予这个站点更高的权重和优先级。搜索引擎在响应用户的检索请求并对输出结果排序时,也会参考该站点的权重。
❑ 保证内容可用。 从客户端的角度来看,如果两个页面是相同的,在其中一个页面访问异常时,可以引导用户查看另一个内容相同页面,这样可以有效地提升用户的检索体验。借助端与云的协同,使用近似重复网页发现,可以改善搜索引擎系统的服务质量。
一般来讲,网页去重的工作还在页面抓取,网页记录到已抓取网页库的阶段完成。当网页爬虫抓取到网页时,如果判断是重复网页,则对其进行去重处理,如果判断为新的内容,则将其入库。
3.重复网页识别思路
重复网页的识别思路是比较容易理解的,主要分为以下4个步骤。
❑对已有的网页文档进行特征提取,生成 n 个特征。
❑对新入库的网页文档进行特征提取,生成 m 个特征。
❑对两个网页文档的特征进行对比,确定相同的特征个数 s 。
❑ m = n = s 则是相同网页,否则取 s /max( m , n )来确定相似率。
上述4个步骤中最关键的是特征提取,关于特征提取的细节不在本书讨论范围内,感兴趣的读者可自行查阅相关的资料。在实际的工程实施过程中,不仅需要考虑算法,还需要看效率、效果及对搜索引擎的策略匹配度。
4.重复网页识别算法
这里主要介绍几个与重复网页识别相关的算法,仅作为指引,帮助读者知道有这些算法和这些算法可以解决的问题,不作深入探讨。在实际应用中,算法实现会比介绍的复杂。
1) MD5算法: 分别对两个页面内容(主要是页面中的文字内容(非脚本))生成一个哈希值,再对两个页面的哈希值进行比较,只要哈希值相同就说明文档完全相同,MD5算法主要识别完全相同的两个页面,相当于 m =1、 n =1,当 s =1时相同, s =0时不相同。
2) I-Match算法: I-Match算法有一个基本的假设,即不经常出现的词(低频词)和经常出现的词(高频词)不会影响文档的语义,所以这些词是可以去掉的,这就相当于比赛评分时要去掉一个最高分和最低分后,再算总分一样。I-Match算法先抓取页面内容进行分词,去掉一些高频词和低频词后,再对剩余的词应用哈希函数进行计算,当两个页面剩余的词的哈希值相同时,说明这两个网页相同。I-Match算法与MD5算法有些相似,只是针对一些不敏感的词进行了优化,更聚焦内容的本身,也相当于 m =1、 n =1,当 s =1时相同, s =0时不相同。
3) K-Shingling算法: 分别生成两个页面的特征,再对两个页面的特征进行相似度的计算。特征提取主要分为三步。
a)抓取网页文档中的关键内容并进行分词;
b)将关键内容拆分为由 K 个连续的词组成的特征组集合;
c)将相同的特征组集合去重。
之后再取两个页面的相同特征数除以两个页面的特征并集(取两个集合所有的元素),即 s /( m U n ),得出两个页面的相似度。
4) SimHash算法: 首先对页面内容进行分词,即将文本拆分成一系列的词(或短语)。然后,对每个词应用哈希函数,得到一个固定长度的二进制哈希值。之后将这些哈希值转化为特征向量,第一位中的值为1则映射为+1,为0则映射为-1。在得到每个词的特征向量后,算法可根据词在文档中的重要性(通常基于词频、TF-IDF等方法)为其分配权重。然后,这些加权后的特征向量会被累加,形成一个表示全文的主向量。接下来,主向量中的每个分量会被符号化处理,将分量大于或等于0时映射为1;小于0时则将映射为0。这样,我们就得到了一个由0和1组成的SimHash值。最后,计算两个页面SimHash值的海明距离。如果海明距离大于系统设定的阀值,则认为它们不相似;反之,则认为它们相似。
当海量的网页数据被网页爬虫技术抓取到已抓取网页库中时,下一步就是把这些数据格式化、索引化,以实现更高的检索效率,这个过程决定了哪些内容可以被用户优先检索到。
1.网页的存储
网页内容在爬虫抓取后存储在搜索引擎的已抓取网页库中,存储的信息包含网页的URL、页面内容、大小、最后更新时间、源码等。
❑ 网页的URL: 主要用于当某个网页被检索到并在结果页中展现时,用户点击该条目,客户端打开这个网页的URL进入落地页以便用户查看详细的内容;在安全干预机制对一些特定的站点进行降级时,也可以通过URL信息进行站点匹配。
❑ 页面的内容: 主要是页面的标题及正文中的文本、图片、视频等内容,基于文本的内容,可以建立文本搜索的索引,以支持文本搜索;对于图片、视频等内容,系统可以对它们进行分类、提取特征、关联文本内容等,使其同样支持被检索。
❑ 网页大小: 主要包含这个页面的主文档(HTML文件)大小,以及打开这个文档加载资源的总大小,这些内容可以帮助后续的排序决策,比如相近的检索匹配度的情况下,在用户为移动网络时超大网页在结果中排序偏后,或者在结果页中提示页面大小,使用户在打开页面时,对移动网络资费的消耗及页面加载的等待时间情况有预期。
❑ 页面的更新时间: 主要用来评估内容的时效性,相似度较低的多个页面,其更新时间越近,内容的时效性越高;搜索引擎中也有提供筛选时间的能力,图3-3是百度搜索引擎提供的筛选时间选项,图3-4是一些搜索结果条目中展现的页面更新时间信息。
图3-3 百度搜索引擎中的筛选时间选项
图3-4 搜索结果条目中的页面更新时间信息
❑ 页面的源码: 存储页面的源码对二次分析页面有直接的帮助,具体的使用场景比如网页正文提取的策略更新/索引更新/网页的安全状态识别等,如果存储了页面的源码,就不需要重新抓取网页,使用入库的数据就可进行二次分析。
2.中文分词算法
在英文内容中,单词之间以空格作为自然分隔符。在中文中,字、句和段由分隔符进行简单的划分,但中文的词没有一个明确的分隔符,需要使用分词的算法来确定。在搜索引擎中,分词应用于不同的场景,比如索引的生成、搜索关键字的理解等。
中文分词的算法主要有两类,基于词典的匹配算法和基于统计的算法。词典匹配算法包括正向最大长度匹配算法和逆向最大长度匹配算法。基于统计的算法包括最大概率分词算法和最大熵分词算法等。
词典匹配算法是比较基础的算法,主要利用正向或逆向最大长度匹配的算法来分词,前提是有分词的词典,这个词典决定输入内容的分词效果。假设词库中有“搜索、客户、客户端、端一、一起、处理”这几个词组,如果对内容“搜索客户端一起处理”,因匹配“客户”和“客户端”时按最大长度优先匹配“客户端”,则分词结果为“搜索/客户端/一起/处理”。
最大概率分词的算法是一种基于统计的算法,主要的实现思路为
1)将要分词的内容切分为多种分词的组合。
2)分别计算不同分词组合的整体概率。
3)取最大概率的分词组合作为该内容的分词结果,比如“有理想抱负”,分词分为两组——“有理、想、抱负”和“有、理想、抱负”,系统分别取这两组词对应的概率进行累计,最终取最大概率的分组,作为该内容的最佳分词组合。
上面提到的这两种算法,都是基于词库的内容进行分词,但是因为人名或地名的词库很难穷举,所以这两种算法用于对人名、地址等内容进行分词时效果就会差一些,这时就需要对姓或市/区等内容的上下文进行联想。通常也会建立多个词库,如常见词、人名、地名、特定词、组织机构等,如何发现新词也是分词系统需要构建的能力,而自动构建新词的能力依赖于自然语言处理(NLP)、机器学习、深度学习等技术,这些内容超出了本书的范围,故这里不进行详细介绍,如果感兴趣可自行搜索相关内容进行学习。
3.索引生成及存储
内容的检索方式主要可以分为两类,一类是通过全文扫描实现全文检索,还有一类是使用索引进行全文检索。
全文扫描的方式是从网页开始到结束来检索网页的内容,类似于Mac/Unix下的字符串检索命令“grep”,全文扫描没有提前对将要检索的内容进行格式的优化,使得检索的内容越多,花费的时间就越长,所以这种方法不适合在搜索引擎中进行大规模的内容检索。
而使用索引的方法,则提前为搜索引擎数据库中的内容建立索引,然后再利用索引搜索相关的内容。这样即使内容量级很大,检索的速度也不会有太大幅度的下降,所以这种方式相对更适合处理大规模的内容,更适合在搜索引擎中使用。故在搜索引擎中,需要将内容预处理为索引,以供后续的检索使用,常用的索引分为正排索引和倒排索引。
(1)正排索引
正排索引简称为索引,主要将页面内容先使用分词程序划分好,同时对每个词在页面中出现的频率、次数以及格式(如加粗、倾斜、黑体,颜色等)、位置(如页面第一段文字或者最后一段等)进行记录。表3-1是页面中的关键词信息示例,页面1中包含1个关键词A和3个关键词C,页面2中包含3个关键词B、5个关键词D及1个关键词E,页面3中包含1个关键词B、2个关键词C及3个关键词E。
表3-1 页面中的关键词信息示例
(2)倒排索引
正排索引还不能直接运用到关键词排名,假设用户搜索关键词B,那么搜索引擎将扫描索引库中所有文件,这样耗时太长无法满足用户快速返回结果的需求,所以这时需要使用倒排索引,对关键词和页面建立映射关系,比如关键词B对应页面2、页面3,这样在检索的过程,直接匹配这个关键词B,就可快速找到对应的页面。简单的倒排索引如表3-2所示,或者在倒排索引表(见表3-3)中增加关键词在页面中出现的频次。
表3-2 简单的倒排索引
表3-3 倒排索引表(含词频)
页面中出现的词频信息代表了这个关键词在该页面中出现的次数,之所以记录这个信息,是因为它在搜索结果排序时会使用到,在用户搜索这个关键词时,当一个关键词在多个页面中都有出现,该关键词在页面中的出现频次是页面排序决策的一个关键因素。当然还有其他的参考因素(比如关键词在页面中的位置),这个是较易实现及统计的。
索引的建立实际上是在解决搜索引擎“快”和“准”的问题,有多种算法可以实现,常见的有两遍文档遍历法、排序法、归并法,感兴趣的读者可自行搜索相关内容进行学习。
倒排索引的建立通常以关键词为维度,存储在磁盘文件中,当有检索需要时则加载对应的文件匹配对应的页面,返回给用户。
4.索引更新
建立索引之后,会不断根据爬虫抓取的新页面对已存在的索引文件进行更新,常见的更新策略包含完全重建策略、再合并策略、原地更新策略。
❑ 完全重建策略: 对已有的索引进行更新,这时搜索引擎继续线上使用老的索引响应用户搜索请求,而新的索引按照新的标准对网页文档进行重建,直到新的索引文件更新完成,搜索引擎切换使用新的索引。
❑ 再合并策略: 对于新增的索引信息,使用新的索引文件(临时索引)保存,当临时索引达到一定的量级时,再进行新老索引的合并。
❑ 原地更新策略: 在老索引文件的尾部增加新的索引信息,通常用于老索引文件还没有加载到内存被搜索引擎使用时。
在实际的系统运行期间,网页爬虫、索引更新、搜索等服务都在并行运行。索引更新需要帮助搜索引擎实现较好的时效性,基于这个目标,索引的更新策略并不局限于上述几种。它与不同类型的内容、业务场景均有关,并且还需要平衡系统的资源消耗,如新闻或事件类的内容更新频次就要高一些,而一些对时效性要求不高的内容,更新频次就相对要低一些。
在内容的检索阶段,搜索服务接收到客户端提交的用户输入的查询内容之后,会对该内容进行分词处理,得到一组关键词。然后,针对每个关键词,从索引文件中检索与其匹配的结果。最后,对不同关键词的结果进行交集运算,得到包含用户输入的所有关键词的网页合集。在此基础上,搜索引擎还会根据自身的策略或业务需求(如添加广告结果)对检索结果进行整合,并将最终结果返回给用户。
本节重点介绍用户输入的容错、取Top K 结果、内容降级这3个检索策略,搜索引擎实际的检索过程要比这些复杂。
1.用户输入的容错
容错机制在每个搜索引擎中均有不同,技术实现思路就是对搜索关键字进行概率预测,即将搜索关键字与系统中的词库进行对比,确定搜索关键字是否有出错可能,并按照概率推荐正确的搜索关键字内容,主要分为音同字不同和字形相似两种容错。
(1)音同字不同
在系统内构建同音词词库,结合输入的关键词内容预测可能需要检索的关键词,并进行推荐检索。比如输入用户想搜索“北京天气”,输入为“背景天气”,系统检测搜索关键词是“背景天气”,从自有的词库中进行容错纠正,实际上为“北京天气”的概率更高,默认在搜索结果中包含“北京天气”,如图3-5所示。
图3-5 音同字不同容错
(2)字形相似
在系统内构建同形词词库,结合输入的关键词内容预测可能需要检索的关键词,并进行推荐检索。比如用户想搜索“已经”,但输入为“己经”,系统检测搜索关键词为“己经”,然后基于自有词库进行容错纠正,最终判断为“已经”的概率更高,默认在搜索结果中包含“已经”的内容,如图3-6所示。
容错处理实际上在解决搜索引擎“准”的问题。上面提到的词库匹配方法是一种比较基础的方法,随着大数据、云计算、人工智能等技术的发展及应用,可以实时、准确理解用户需要搜索的内容。客观地讲,在单字的情况下,搜索的容错机制就会失效,因为概率上输入哪个字都是正确的,缺少了纠错的参考。
图3-6 字形相似容错
2.取Top K 结果
在用户看到的检索结果中,通常排在前面几页的检索结果质量是最好的,更符合用户的需要。一般来说,与搜索需求越相关的页面在检索结果中的排名越靠前,用户越能以较快速度找到所需,搜索体验也就越好。搜索结果排序的合理性,基本上决定了这个搜索引擎的检索质量。
用户在浏览搜索结果时,如果在前几页中没有找到结果,大概率再往后翻也不会找到与这个搜索关键字更相关的内容了。资深的搜索用户这时通常会更换搜索关键字,或更改搜索条件以获得更精确的结果,甚至还会更换不同的搜索引擎进行检索。一般搜索引擎也不会将所有的检索结果都返回用户,基本都不会超过100页(如果有兴趣可以试着翻翻,看100页以后搜索引擎会显示什么),而且一页只显示12个相关检索结果。也就是说,搜索引擎其实只需要选出Top 1200个结果就够了。
在搜索引擎这种大规模信息检索系统中,对检索出来的结果进行排序是一个非常核心的环节。这个排序可以通过搜索引擎对符合用户需要的检索结果进行打分,从中选出得分最高的 K 个检索结果的过程来实现,这个过程即To p K 检索。
Top K 检索可以解决搜索引擎“快”和“准”的问题,如图3-7所示,用户输入“架构”这个搜索关键字进行搜索时,Google搜索找到了约1.65亿条相关结果,从数据的量级来讲用户根本不会浏览这么多的内容,从相关性来讲越往后的内容相关性越低,即便可以为用户展现,一些内容也是没有意义的。如图3-8所示,在用户实际浏览过程中,仅展现了228条结果,取To p K 个结果,会提升检索的速度,降低系统资源的消耗,是一种优化搜索的策略。
3.内容降级
前面提到网页爬虫的时效性问题,即经网页爬虫抓取的内容入库后,可能存在该链接的 内容变更 的情况,也可能存在 内容不可用 的情况。内容降级是优化搜索结果的一种保底策略,目的是避免因这两种情况,导致页面被检索到并作为结果返回给用户时,用户无法浏览到预期内容,从而对用户的搜索和浏览体验造成干扰的情况发生。内容降级实际上是解决搜索引擎“准”的问题,常见的降级原因有以下两种。
图3-7 搜索结果页中展现的相关结果数量
图3-8 实际浏览过程并不需要所有的结果都浏览
❑ 安全原因: 当网页中包含浏览体验较差或者不适合用户浏览的内容,这些内容一旦被识别到,系统则可以通过干预手段让这些内容不被检索到,从而避免用户看到这些内容产生影响或不适。当然,这项识别能力如果可以通过自动化实现是最理想的,实际上现在的技术还做不到完全精准的主动识别,大部分的场景还是被动防御。
❑ 页面或站点无法访问: 当某个站点出现大规模的访问异常时,系统就可以对这个站点进行干预,避免其内容被检索到,但用户无法浏览的情况。有时网页爬虫在抓取网页时网页内容是有效且可访问的,但用户点击打开该页面时内容却不能访问了,这是因为两者存在时间差。在这时间差内,站点内容的更新策略和运营状态都会影响入库的网页是否可打开及浏览。
从理论上讲不能正常打开的网页是比较容易通过大数据手段识别出来的。比如,在同一个时间段,同一个页面或站点有多个用户无法打开,且这部分用户是访问该页面或站点的全集,这时就可以判定这个页面或站点处于异常状态。技术方案要么是在服务端实时监测,要么是在客户端打开页面时进行检测。若采用前者,则要求服务端有极高服务带宽,不过,服务端对站点的访问容易被拒绝。若采用后者,客户端在用户浏览过程中就可以识别及上报异常,之后可以在服务端进行大数据的计算得出页面或站点的异常状态,这就是自有搜索客户端的好处。
客户端提交搜索关键字后,搜索引擎的检索服务端会提取这些关键字,并根据系统的检索策略生成有序的搜索结果。这些搜索结果是一堆结构化的数据,为了将结果展示给用户,需要根据产品需求将这些结构化的数据转换为网页格式,使它们可以在客户端渲染及交互。这就是搜索结果的产品化封装过程,该过程由搜索引擎的前端服务完成。
转换成网页格式的搜索结果,既可以在自有客户端中展现,也可以在浏览器中打开。因为用户的设备中都预置了默认浏览器,相当于用户可以零成本地使用搜索服务。
通过对比不同App的搜索能力,可以发现不同App内的搜索结果中,各种类型的结果条目的展示形式各有不同。作为搜索服务的一部分,搜索前端在对搜索结果进行产品化封装时,通常是根据检索服务端检索到的结果条目类型来确定每类条目的展示形式的。
从架构设计的角度来讲,检索服务端返回结构化的数据,在搜索引擎的前端服务对搜索结果进行产品化封装。这两种服务相互独立、并行的演化,是常见的模式。搜索客户端在提交搜索请求时,先提交到搜索前端,再到检索服务端(透传搜索关键字),检索服务端进行内容检索并返回结构化的检索结果,搜索前端将结构化的数据转换成网页格式即进行数据封装后再返回给搜索客户端,搜索客户端通过浏览内核加载结果页,用户看到搜索结果,进行浏览,点击进入落地页直到找到所需。基本的搜索客户端、搜索前端及检索服务端协同的流程如图3-9所示。
图3-9 基本的搜索客户端、搜索前端及检索服务端协同的流程
有了自有客户端,搜索结果页也可以是非网页格式,端云协同可以实现自定义的数据展现、交互的能力。这样就可以支持结果页的差异化定制,如果仅对结果页的展现和交互进行优化,则调整搜索前端即可。而如果要对搜索的结果及策略进行优化,则需要统一调整检索服务端相关节点。
实际的搜索产品的完整部署比上面提到的要复杂得多。例如,需要考虑负载均衡、异常降级等问题。此外,检索服务端可能需要处理多种类型的内容检索(如网页内容、自建内容等),并且可能需要合并多种类型的搜索结果。这些能力会随着搜索业务的变化而不断调整,有点类似于客户端上的模块划分。但是在服务端,这些能力会被拆分为不同的服务,它们之间相互依赖、相互支持。
前面讲了关于搜索引擎的内容生成相关知识,本节从客户端的角度对搜索过程进行梳理,搜索过程主要分为10个关键步骤,如图3-10所示。
图3-10 客户端与搜索服务协同的10个关键步骤
1) 用户 输入搜索关键字后,点击搜索。
2) 客户端 响应搜索指令,将用户输入的搜索关键字拼装到URL中,并通过浏览内核请求加载该URL。
3) 客户端 展现页面加载态,为用户指示页面加载过程,避免用户因等待时间过长误以为无响应的情况发生。
4) 搜索前端 接收网络请求,从URL中提取搜索关键字及相关参数,并将搜索关键字和相关参数提交给检索服务端。
5) 搜索前端 记录客户端的请求,也记录予检索服务端的搜索请求。
6) 检索服务端 对用户输入的搜索关键字进行容错处理,得出用户可能想要输入的内容,这一步在用户输入的都是没有歧义的搜索关键字时可以省略。
7) 检索服务端 取Top K 结果,根据用户输入的搜索关键字(系统容错处理后的),进行相关内容的检索。
8) 检索服务端 进行内容降级,将检索到的Top K 结果中的一些不适合的内容移除,不作为搜索结果展现给用户。
9) 搜索前端 接收搜索结果,对结构化的数据进行产品化封装,即将搜索结果按照可展现、可交互的格式进行封装,对于浏览器产品通常是网页格式,对于自有客户端既可以是网页格式,也可以是自定义格式。最后,把封装后的数据返回给客户端。
10) 客户端 收到搜索前端返回的结果,加载相关的内容及资源,在客户端解析渲染,将结果展现给用户。
上述10个关键步骤基本覆盖了在满足搜索需求的过程中,搜索客户端、搜索前端及检索服务端的协同过程。实际中,为了支持深度的优化及定制化,该协同过程的设计与实现要比这个更复杂和精细。
自有搜索客户端可以实现许多原本在浏览器中无法实现的功能。与在浏览器中打开的页面相比,自有搜索客户端可以构建与搜索引擎相关的指标,从而为优化搜索引擎结果提供数据支持。本节主要讨论自有搜索客户端相对浏览器在支持搜索服务优化方面的技术可行性,仅代表个人从客户端视角看到的可优化点。
1.搜索结果精细化
在浏览器中打开搜索引擎页面进行搜索和浏览时,由于搜索引擎页面和第三方页面的生命周期差异和数据隔离,导致用户的行为是不连续的。在自有的搜索客户端中,用户从输入搜索关键字到打开搜索结果页,再到打开某个结果的落地页,整个搜索流程的数据是完整的、可知晓的,如图3-11所示,因此可以更精确地追踪搜索行为的来源。
同时,在搜索客户端中可以获取更多与用户相关的特征信息,这些特征信息可以在搜索过程中一同上报到搜索引擎,从而实现搜索结果的精细化。例如,用户浏览某一类内容的时间较长,可以说明用户对这类内容感兴趣。
2.搜索结果的异常识别
搜索引擎中的内容数据一旦入库,相关网页信息将被存储在系统数据库中,直到在下一个周期更新数据库时,才对数据库中的相关网页信息进行更新。这个过程存在时间窗口期,并非实时的运行。当某个站点或页面出现异常时,无法立即发现。
图3-11 搜索客户端可覆盖完整的搜索流程
自有搜索客户端可以在用户打开落地页产生了异常时捕获到异常信号。当一个页面有多个用户在相近的时间段内打开浏览时,出现了异常,那么这个页面就存在异常的可能。
如果同一个站点下的多个页面在同一时间段内均出现异常,这可能意味着该站点或其子路径出现了异常,如图3-12所示,第三方页面异常识别上报到服务端后,服务端可通过多方认证确定站点或页面是否存在异常。为了确保用户检索结果的有效性,更新该站点在搜索引擎中的数据及排序权重,这时搜索客户端和浏览器,均不会搜到这个异常站点的内容了,用户的搜索体验得到了保障。
图3-12 多方认证识别页面异常
3.搜索结果安全状态识别及干预
搜索引擎也是个产品,不仅可以为用户检索到想要的内容,还可以根据自身的产品定位,对用户优先展现与产品定位最相符的内容,产品定位也会影响搜索引擎的入库和检索策略。但是,互联网是一个开放的生态,总会出现一些与产品定位不符的内容,比如涉及黄色、暴力的信息,以及窃取用户隐私、财产信息和违反政策法规限定的内容等,这些一般不会推荐给用户。
然而,一些站点也在与搜索引擎进行博弈,以便上述不良内容也可以被用户搜索到,例如,利用搜索爬虫抓取内容的时间周期性,调整站点在爬虫抓取时和用户浏览时的内容。为了实时发现和精确识别这类内容,可以借助于搜索客户端,在用户浏览的过程中提取关键的特征信息,以进行页面类型的识别及干预,之后将这些信息同步至搜索引擎进行内容的优化。如图3-13所示,搜索客户端识别并上报页面的安全状态,服务端经过多方认证发现不安全的页面,从而进行搜索干预即更新数据及排序权重,干预效果同样也影响浏览器用户,基于这样的思路,因为有了搜索客户端,使得搜索服务的体验在各端均变得更好了。
图3-13 多方认证识别页面安全状态