封掉Google——《神秘的程序员们》系列漫画

这个系列的漫画讲述程序员——这种神秘人类的囧事,故事多来源于我身边的程序员朋友,且以互联网开发背景为主。

如果你有什么可乐的关于程序员的故事、对话、代码,愿意通过漫画的形式分享,请给我发邮件。arthur369@gmail.com

cc

如何搞定站内搜索的产品设计及应用(上)http://blog.xiqiao.info/2009/06/02/343

如何搞定站内搜索的产品设计及应用(中)http://blog.xiqiao.info/2009/06/03/357

如何搞定站内搜索的产品设计及应用(下)http://blog.xiqiao.info/2009/06/19/388

六 站内搜索的开发

我写下面的关于站内搜索的开发,是尽量用浅显的语言来解释开发原理和程序请求的流程,主要给非专业的技术人员看。

搞产品应该懂得起码的开发原理,不要浮于专有词汇的表面。况且了解原理这事只要破除迷信,多读点真东西,一点都不难,也没有什么所谓的学科门槛之类的。我很想写一篇《搞产品应该懂的数据库命令》,来破除下非技术人员的代码恐惧症。

站内搜索的技术流程是:

  • 第一步 提取原料:抓取网站页面或格式化数据
  • 第二步 把原料归类:建立索引,把关键字和页面一一对应上,分类放好(想象一下老式图书馆里的归档管理方法就能形象理解索引了)
  • 第三步 听用户要上啥菜:响应用户的搜索需要,对用户输入的关键词进行分解,从索引中找到符合该关键词的所有相关网页。
  • 第四步  摆盘上桌:对搜索结果页面进行排序,将页面标题、url、摘要等信息呈现给用户。

一步步细说:

第一步:提取原料:抓取网站页面或格式化数据。

抓取页面是使用一种叫蜘蛛的程序,一个网站中成千上万个页面是通过什么关联起来的?url。蜘蛛就是通过一个页面的url找到另一个页面再找到另一个页面,把所有能链到的页面遍历一边,记录下来。

通用搜索引擎(google baidu)的蜘蛛 很复杂,因为一个页面上可能有很多个url,每个url又关联着无数页面,整个网络像一棵树,假设首页是第一层,首页上的url关联的页面是第二层,第二层页面上url关联的页面是第三层……

蜘蛛抓取的顺序就会很重要,是沿着一个url一直爬下去,还是先爬完一层再爬一层;加密或需要用户登录后才能访问的内容怎么抓取;pdf、rar及多媒体文件怎么抓取,都有讲究。不同的抓取处理在有效性、效率和对 被爬网站的资源占用 上有很大差异。

当然站内搜索没有那么麻烦,一般是技术人员根据希望被纳入搜索的内容数据库 生成一份格式化的 xml文档,让蜘蛛直接抓取就行了。但是站内搜索在提抓取页面更新索引时,有一个指标比较高,那就是抓取的更新频率。

比如对于电商类网站,某些商品,特价、抢货啦,可能刚发布出来5分钟就卖完了,或者改价格了。但是用户听说促销啦,来网站上一搜,搜不到,或者搜到了点进去发现价格不对,用户就会不舒服。 这就是蜘蛛抓取页面的更新频率过低导致的。要解决这个问题并平衡性能与资源占用之间的矛盾,需要多种算法组合优化。

通用搜索 比如google、twitter在做这方面的努力,也就是做成实时搜索。但是站内搜索服务还鲜有尝试者,霍炬余晟最近在做针对电商类的优化。目前可以做到即时更新,也就是发布后1分钟内就可以被搜索到。

第二步:把原料归类:建立索引。

建立索引这一步 集中了搜索引擎 的两大核心技术难点:索引结构和中文分词

如果按照正常人的思维,索引应该是这样建立的:

  • 把每篇文章存在文章索引表里(假定我们叫它doc索引),然后解析出该文章中有多少关键字,把关键字存在一个表里(我们叫它keyword索引)
  • doc索引的大致结构就是:docID  | doc标题/内容 | doc的url及其它信息 | doc中每个keywordID 。
  • 当用户输入关键字搜索的时,先找到关键字对应的keywordID, 然后查找到有哪些doc里包含做这个keywordID。

这种思路很符合逻辑,但是不好意思,在效率上几乎是不可行的。

因为在查找哪些doc里包含这个keyword的过程相当于 哗哗哗狂翻一本书来找里面的一个词。网站的doc索引条目动辄上万上十万,要是同时查找多个关键字,相当于多次狂翻一本十几万页的书,你说是不是累死了。

于是 就有一种更符合 程序运行方式的 索引建立方法。这就是倒排索引,也叫反向索引。 而上文中提到的符合正常人思维的叫正排索引

倒排索引中“倒”的含义是指把doc索引和keyword索引的关联次序颠倒过来。在建立索引的时候,先建一张keyword表,结构是:“keywordID  | 关键字 | 存在哪篇doc中的哪个地方 ”

“存在哪篇doc中的哪个地方” 这个信息怎么表示?

通过一种叫映射的方法。通俗地举例:“北京”这个词出现在 id为0011文章的第2段第5行第3个字,可以表达为一个字符串 0010p2l5f3,所以“北京”这个词在keyword表里是可能这样写

“ k001 | 北京 | 0010p2l5f3 , 0010p5l1f9, 0012p1l2f6……”

这是一个平面的结构,实际程序中当然不会这么简单处理,这样效率还是太低。会处理成一个有层次的结构,比如第一层只存docID  “k001 | 北京 | 0010,0010,0012……” ,第二层再存是属于哪一段哪一行等。

这样做的好处是 可以在第一层实现一次归并。因为搜索结果页面最先需要列出的只是那篇文章里包含哪个关键字,不需要具体位置,所以,当北京这个词在0010文章中多次时,第一层索引可以归并为为 “北京| 0010,0012 “ 这样结构又精简了。

索引的结构及存储方法对 搜索速度起致命的影响。

分词: 中文分词技术是中日韩语专属的一个的高难度课题,研究了十几年了。而英文每个单词之间都有空格,没这个麻烦。

比如 “作家长平时常翻阅这本书” 这句话 人可以识别“ 作家 长平 时常 翻阅 这本 书”。但是计算机可能就分成了“ 作 家长 平时 常 翻阅 这本 书”。计算机不认得“长平’ 这个人名,导致分词错误,用户搜索长平的时候就得不到这条结果。

再例如,当用户输入 “和服”搜索时,出来第一屏都是 “产品和服务”,“化妆和服装自己搞定”,用户是不是很郁闷。

所以分词技术 对于 搜索的准确有效性 起关键作用。

基础的分词方法是机械切分,也叫二元切分。以2个字为一个单位进行切分,不进行判断,比如 中华人民共和国 -> 中华 华人 人民 民共 共和 和国

在此基础上进化出了双向最大切分,就是把一句话切成最小词单元,正向切分一次,再反向切分一次,比较下哪个更合理,再通过复杂算法识别出有效关键字。

更先进的方法是在机械切分的基础上使用合理的词库,地名、品牌名、机构、简称等需要词库。而不同行业如金融类、计算机类、商品类都有不同的专业词库。

还有基于人工智能和统计概率的分词算法,但是对于站内搜索这个量级的都不适用。

对于站内搜索而且,除了好的分词算法,更重要的是词库添加和统计功能。网站管理员可以根据用户搜索行为的统计分析 手动向词库内添加新词。

第三步:听用户要上啥菜:响应用户的搜索需要

  • 用户输入的搜索条件可能是一句话,所以对用户搜索请求的解析也要用到分词技术。如果搜 “吉野家沙拉” 和 “吉野家 沙拉” 会得出不一样的搜索结果,就是比较差的搜索引擎了。
  • 用户输入的关键字是对词库的有利补充。比如搜全聚德的人多了,全聚德显然是一个有效的专业词汇。
  • 多个搜索关键字之间存在逻辑运算关系。逻辑运算。。不要怕,搞设计的人应该都知道布尔运算。。不知道?总知道反选、多选、选区交集吧。这就是逻辑运算中 非运算(not)、  或运算(or)、 与运算(and)

用户的搜索条件是“美国 金融危机”如果采用 或运算,则文章中只要包含了 美国 或 金融危机 这两个词中的一个,都有可能被列为搜索结果。 如果采用 与运算,则只有同时包含了 美国 和金融危机这两个词的文章 采会被列进搜索结果。

所有搜索引擎都应该在输入搜索条件时,支持逻辑运算符。

对于通用搜索引擎,一般 多个关键词之间的空格 就默认代表了是 与运算(and) 的关系。可以通过输入逻辑运算符 来完成其它搜索需求。比如 可以使用 “哈希 or Hash” 来搜索更多关于哈希算法的信息中英文都有, 也可以使用 “小李飞刀—电视剧” (减号)来搜索除电视剧外的小李飞刀的信息。

对于站内搜索,1 没有通用搜索那么大的数据量 2 比搜索引擎专业性更强。所以站内搜索 多个关键字之间的空格 默认代表的是 或运算 的关系。但是会在呈现结果的排序上做文章,通过多种算法计算出相关性最高的文章排在前面,相关性弱的排在后面。这样可以帮助用户发掘到更多 关联性内容,结果呈现也更人性化。这是通常定义下的 站内全文检索 的一个重要特征。也是区别于数据库搜索的技术优势。

响应用户搜索条件的时候 还有字段匹配及权重的问题,一篇doc 可能有标题、摘要、正文、tag、作者等多字段信息存在doc索引库里。Keyword是出现在标题、摘要还是正文中时,权重是不一样的。

第四步 摆盘上桌:对搜索结果页面进行排序,

琢磨过SEO的同学一定知道,所谓搜索引擎优化 1是让蜘蛛能抓取自己网站上更多的页面2 让自己网站的页面在搜索结果里能排得更靠前。

这就要研究搜索引擎的排序算法。对于各个通用搜索引擎,排序算法是许多人的关注核心,每次权重调整都会带来巨大震荡。通用搜索引擎都是在基于相关性排序上在加上各自的算法,如Google的专利pagerank就是通过页面之间的互链来判断页面的价值高低,再加上链接引用页面的PR值、是否在一个分类等 各种其它指标。

但是站内搜索,用互链这种方式来判定显然不靠谱,所以主要还是通过优化相关性的算法,计算keyword和DOC之间的关系,例如 keyword 在doc中出现的密度,词频, doc是否和 keyword 属于同一语义类别,doc的长度属性(短的doc应该降权之类的)等判定 keyword的搜索结果中,哪些doc更重要更有价值。

多个关键字的搜索条件,让算法更复杂,如何对多个关键字进行比较、两者的结果如何合并,两者的结果顺序如何穿插重排。

最后还要利用算法来优化 结果排序的速度和稳定性

由此 才能得到站内搜索的相关度排序结果。

————————————————————————————

上面基本讲了站内搜索的原理,看到这会有很多人觉得站内搜索的开发是一个技术要求很高的应用。也的确是这样,一般网站很难养得起一批能开发搜索引擎的工程师,开发周期上也承担不起,关键也缺乏持续改造的动力。产品设计人员也很难想在这个重要应用上有所发挥,对产品进行一点优化和改造都会牵扯到巨大的开发工作量和成本压力。

搜索引擎核心和分词 现在有一些开源代码或开源词库可以使用,也可以选择租用成熟的站内搜索服务来解决开发问题。使用SAAS (软件即服务模式,现在一种流行的技术外包服务模式) 的优势在于可以根据网站的去业务逻辑定制搜索模式,且搜索这部分的数据结构是单独建立重新格式化过的,对站内搜索进行产品改造不会对网站本身的业务逻辑和数据结构造成任何影响。也可以不占精力成本地享受产品改造技术升级的好处。

如何搞定站内搜索的产品设计及应用(上)http://blog.xiqiao.info/2009/06/02/343

如何搞定站内搜索的产品设计及应用(中)http://blog.xiqiao.info/2009/06/03/357

五、站内搜索的其它应用

1. 流量引导

针对站内搜索本身,流量引导的主要方式是关联、推荐和热榜。

  • 关联: 包括搜索结果关联、关键字关联 和推荐内容的关联。如,关注该关键字的用户还搜索过,买了此类宝贝的用户还买过
  • 推荐:根据用户搜索的需求分类 推荐相关的网站内容或商品。
  • 热榜:热门关键字排行,或上升快的热门关键字排行。

2. 特殊情况的设计:

当用户的搜索行为无搜索结果时、用户的搜索行为有输入错误或障碍、搜索结果过少时。

由用户行为造成的无结果或少结果,有下列几种状况:

  • 用户拼写错误。
  • 用户输入了限制过多的关键字条件
  • 用户误操作。

处理上述状况,首先应该由程序判断是否存在输入的拼写错误,在搜索结果之前首先提供纠错建议,提示和引导用户进行有效的操作,并根据数据挖掘,提供能满足用户搜索需求的有效关键字。如:“没有找到相关结果,不如试试搜索****。”等。

如用户输入了过多的关键字条件,(如用户直接在搜索框里粘贴了一句很长的话,且搜索设置为多关键字之间的匹配关系是与运算)应建议用户使用正确的条件输入方式。

误操作的状况多出现与用户直接点击了搜索按钮而没有输入关键字。这种状况不同网站有不同处理。如页面刷新、跳转到搜索结果页面但提示误操作、blank跳转到目录或索引页面、js弹窗提示误操作等。

非用户行为造成的无结果或少结果,有下列几种状况:

  • 分词错误:例如人名、专有名词、地名等专业词汇被错误地分词,造成有效结果不多。
  • 无有效数据

上述状况都应该在搜索功能的管理设置中有所反映,必须有手工补充关键词库的功能。必须能对少结果或无结果的关键词进行数据统计,以帮助决策内容维护方向。

另一种状况是当搜索结果过多时:用户输入了一个涵盖范围太广的关键字,搜索结果多于20页的时候。

宽泛的关键字定义不能帮助用户有效完成搜索目的,用户翻20页以上去检索的可能性很小,对网站性能也会造成不必要的浪费。

所以在搜索结果页面提供分类和筛选是首要前提,也应该在适当的位置体现用户使用关键字组合的正确方法或使用分类、筛选功能。

在分页设置上,可以以只显示20页为一个区间。

3. 内容价值的优化处理

在论坛、知道、百科之类应用中,设计者比较不愿意看见的一个状况就是问题和条目的重复,既浪费资源、分流用户贡献的有价值内容,也不利于信息组构。(流量膜拜主义的不在此列)

这类应用中,可在用户提问、发帖的title输入框旁边放置搜索提示或搜索框,引导用户在提问之前先搜索。

这个类应用可以通过搜索功能对内容价值进行优化。

4. 海量信息或历史内容的价值最大化

对于新闻、资讯、论坛站这类海量信息站而言,信息结构的设计是极为重要的,仅将内容价值建立在热门话题和更新速度上,是一种不明智和浪费的运维思路。好的信息结构设计,让用户不会在扫完热门和更新内容后就无事可做,降低用户跳出率、提高单ip的页面浏览数。设计思路除了明晰合理的多级信息目录结构,还应该根据运营需求建立起 话题眼、新闻脉络、信息时间轴 等内容聚合点和内容聚合线索。

搜索和数据挖掘是帮助优化此类设计的重要选择。

百度贴吧的伟大之处在于极大地发挥了由搜索关键字创建话题眼这一设计。

说到这,可能有人已经联想到了 tag 埋在正文中的关键字链接

对于论坛 或 非正规的信息站而言,通过tag来支撑一套信息维度是不现实的。

而正文中埋链接,多用于 产品库(名人库)这类专有词,主要用于导流量,在文中高密度使用也是不现实的。

所以使用分词技术或词频分析,在某篇文章中获取核心关键字后,在侧栏或标题/正文下方列出,是一个很好的处理方法。这种流量引导方式比“相关新闻”赋予用户更大的选择性,也更利于用户深度挖掘内容发现内容。

通过处理发布时间排序,可以形成以时间为脉络 新闻线索。

银杏搜索和我曾经提出一个概念产品设计,用于大型新闻/资讯网站的新闻搜索,让新闻关键字成为一个信息时间轴。

这个产品可根据某个关键字的搜索结果在时间轴上的分布,按时间区间输出搜索结果量的指数图,体现出到该关键字的新闻性时间趋势。

当鼠标移上某个节点,会显示该节点的日期和详细结果数。

用户可以通过点击年份,放大趋势图,查看某年的搜索结果的详细指数图。

这个产品可以很容易通过时间体现新闻趋势,强化传播的时间维度上的表现力,用户体验新鲜,更重要的是可以利用埋藏着的历史信息实现价值最大化。

这个应用还可以扩展为更高端的趋势比较。当用户输入2个以上的关键字时,可以在指数图中看见两个关键字的对比折线图,用户可以对两者搜索结果在时间分布上进行趋势比较。

5. 应用于内容发布系统

站内搜索除了在前端使用,在信息发布系统中也有重要的应用。典型例子的是帮助使用者筛选相关新闻(包括专题组织中的相关新闻列表)。

我讲一个我遇到过的案例:传媒类网站的cms系统,最初的设计:使用者点击“查找相关新闻”按钮,blank弹出结果页面,搜索条件直接取值于文章title和tag,全文检索。但使用者总是对筛选出来的相关新闻不满意,觉得匹配度不够高。

例如

  • 当使用者 为 ********(上)查询相关新闻时,当然最希望出来的是*******(中)和*******(下),但是标题被分词以后,再加上tag,由于词频权重的原因,中和下篇可能并不是排在前头。
  • 当使用者为一篇标题里包含 美国银行 这个词的文章查询相关新闻时,排在前几位的可能和美国银行没关系,而是奥巴马竞选或中美外贸。这是因为美国银行会被分词,拆为美国和银行,出现美国或银行频度最高的文章会被排在最上面,如果美国和银行之间采取 或运算 的话,结果就更糟糕。
  • 经过沟通和分析使用者需求,我把一个“查找相关新闻”按钮,拆分成了3个按钮,以满足使用者不同的搜索意图。

    • 按钮1 “根据标题精确搜索”,用于查找系列文章,多个关键字之间采取 与运算,满足精确关联需求。
    • 按纽2 “根据作者搜索” 仅匹配作者字段,用于精确查找该作者写过的所有文章。
    • 按钮3“相关性搜索”,匹配title分词和tag,满足查找宽泛关联的需求。

    客户此后就满意了,几乎不再需要手工自定义搜索条件,提供了处理效率。

    这个案例的启示是:1 站内搜索的应用设计中,搜索条件提取、多关键字的处理、匹配字段的处理 这些设定的变化,能对搜索结果、应用效率造成巨大差异,好的应用坏的应用由细节中产生。2 通用化设计往往是最不易用的。

    图形界面——《神秘的程序员们》系列漫画

    图形界面——《神秘的程序员们》系列漫画

    这个系列的漫画讲述程序员——这种神秘人类的囧事,故事多来源于我身边的程序员朋友,且以互联网开发背景为主。

    如果你有什么可乐的关于程序员的故事、对话、代码,愿意通过漫画的形式分享,请给我发邮件。arthur369@gmail.com

    事物的本质——《神秘的程序员们》系列漫画

    事物的本质——《神秘的程序员们》系列漫画

    在霍炬的鼓励下,我决定创作关于程序员的漫画。我已经不动笔好几年,当然动笔之前水平也够烂~~

    这个系列的漫画讲述程序员——这种神秘人类的囧事,故事多来源于我身边的程序员朋友,且以互联网开发背景为主。

    如果你有什么可乐的关于程序员的故事、对话、代码,愿意通过漫画的形式分享,请给我发邮件。arthur369@gmail.com



    Copyright © 2007–2013. All rights reserved.

    RSS Feed. powered by Wordpress a theme by Xiqiao.