主流搜索引擎对用户点选命中的处理

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

可能是因为存储成本的降低吧,现代搜引擎对数据的收集都是贪婪的。原来Google在首页上放了一个页面索引数量,记得最高已达到了8个多billion的页面数。另外搜索引擎记录用户搜索的关键字已不是什么秘密,但是大多搜索引擎还记录了用户点选命中。

    用户点选命中这个概念是包含于搜索引擎命中这个范畴中的。搜索引擎的命中,就是你敲入关键字后,搜索引擎返回的所有结果。搜索引擎有效命中,是指找出与搜索关键字含义相匹配的网页。而用户点击命中,是指用户在搜索命中的结果中,发现了自己需要的结果,然后点击的网页链接。

    搜索引擎命中、有效命中和用户点选命中之间的关系如下图:
    SearchResult.png
    绿色的Matched Pages是理想的和关键字完全相关的页面。金黄色的Result Pages就是搜索返回的结果集,它与Matched Pages交集的多少,决定了搜索引擎的质量。蓝色的Clicked Pages就是用户点选命中,它是一个很特殊的区域。首先它一定是被限制在金黄色的Result Pages中,然后由于这个点击是每位搜索用户根据网页标题以及摘要判断后进行的,它将最大限度的包含在Matched Pages中,当然少量判断错误的情况也很自然,所以Clicked Pages又不会完全在Matched Pages中。

    当搜索引擎记录了Click Pages后,它就可以根据这个记录,调整Result Pages集和该集内条目的排序,把总是不被Click的页面逐渐移出该集合,而将更多将可能的Matched Pages命中移入。即图中A-->B的变化过程,当然理想的情况是Result Pages就是Matched Pages啦,并将Clicked多的结果条目尽可能往前排。目前的主流搜索引擎:Google、Baidu、Yahoo和微软Live,其中除了baidu外,其它三种引擎都可能收集了Clicked Page,不过他们在实现技术上又有所差别。

    Google收集方案:简单、优雅
    Google-ABIS.png
    // 最初好像这里是指向的google的页面,然后再重定向到目的页面

    当然这里的link,Google对其进行了处理:<class=l href="http://bi.u-soft.com.cn/Products/ai2005/" target=_blank onmousedown="return clk(0,'','','res','1','')">极光商智2005概览- 宏信极光商智</a>。简单的加上了一个onmousedown事件,clk函数定义如下:

None.gifwindow.clk= function(b,c,d,h,i,j)
ExpandedBlockStart.gif ContractedBlock.gif dot.gif{
InBlock.gif     if(document.images)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         var a=window.encodeURIComponent?encodeURIComponent:escape,e="",f="",g="";
ExpandedSubBlockStart.gif ContractedSubBlock.gif         if(b) dot.gif{e="&url="+a(b.replace(/#.*/,"")).replace(/\+/g,"%2B")}
ExpandedSubBlockStart.gif ContractedSubBlock.gif         if(c) dot.gif{f="&oi="+a(c)}
ExpandedSubBlockStart.gif ContractedSubBlock.gif         if(d) dot.gif{g="&cad="+a(d)}
InBlock.gif        ( new Image).src="/url?sa=T"+f+g+"&ct="+a(h)+"&cd="+a(i)+e+"&ei=hhp7RfHwGpnIwQKr-qiTCA"+j
ExpandedSubBlockEnd.gif    }
InBlock.gif     return  true
ExpandedBlockEnd.gif}

    // HTML元素中,除了Image可以直接new外,还有Option对象也可以直接new,不过我也不清楚为什么要这么设计

    代码混淆过,相当不可读,不过这不是我们关心的重点。这里可以看到Google巧妙的使用了Image对象会预先载入图片的技巧,实现了Clicked Page的回报。这里图片的实际地址是:/url?sa=T&ct=res&cd=1&ei=hhp7RfHwGpnIwQKr-qiTCA,其中的ei=hhp7RfHwGpnIwQKr-qiTCA,应该是连接标识。对该图片访问后的返回结果,Google是做了最佳优化处理的,该请求返回的http响应是204,即:

None.gifHTTP/1.1 204 No Content
None.gifCache-Control: private
None.gifContent-Type: text/html
None.gifServer: GWS/2.1
None.gifContent-Length: 0
None.gifDate: Sat, 09 Dec 2006 20:41:45 GMT

    // 关于http协议204的解释请参看RFC2616

    微软Live收集方案:简单、臃肿
    Live-BI-ABIS.png

    怎么简单又臃肿呢,这不是自相矛盾吗?简单是说Live也是用Image对象相来报告Chicked Page的,而臃肿是说微软的这个Live的页面。微软也是简单的对link进行了处理:<href="http://yyq123.wordpress.com/2006/04/" gping="/GLinkPing.aspx?/_1_9SE/1? http://yyq123.wordpress.com/2006/04/ &amp; &amp; DI=6244&amp; IG=e982db6143c048488736e2f890c94aa9&amp; POS=1&amp; CM=WPU&amp; CE=1&amp; CS=AWP&amp; SR=1&amp; sample=0">2006 April « 语虚</a>。似乎是只加了一个gping的自定义属性,但接下来的事情就会让你晕倒死。。。

    完成GLinkPing(名字取得不错,但怎么感觉是尽整没用的呢)功能的脚本代码为:
  

None.gifGTracking.GLink =  function()
ExpandedBlockStart.gif ContractedBlock.gif dot.gif{
InBlock.gif     var TIMEOUT = 3 * 1000;
InBlock.gif     var _timer =  null;
InBlock.gif     var _img =  null;
InBlock.gif     var _bIsIE =  false;
InBlock.gif     var _clickedAnchor =  null;
InBlock.gif     var _mouseCapturedElement =  null;
InBlock.gif
InBlock.gif    bind_method(document.body, "mousedown", onMouseDown,  false);
InBlock.gif    bind_method(document.body, "mouseup", onMouseUp,  false);
InBlock.gif    bind_method(window, "unload", onUnload,  false);
InBlock.gif
InBlock.gif     if(document.body.addEventListener)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif        _bIsIE =  false;
ExpandedSubBlockEnd.gif    } //  document.body.attachEvent is added by atlascompat.js and will confuse this code if loaded.
InBlock.gif
     else  // if(document.body.attachEvent)
ExpandedSubBlockStart.gifContractedSubBlock.gif
     dot.gif{
InBlock.gif        _bIsIE =  true;
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function onMouseDown(theEvent)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         if(_bIsIE)
InBlock.gif            _mouseCapturedElement = window.event.srcElement;
InBlock.gif         else
InBlock.gif            _mouseCapturedElement = theEvent.target;
ExpandedSubBlockEnd.gif    }
InBlock.gif    
InBlock.gif     function onMouseUp(theEvent)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         var evt;
InBlock.gif         var src;
InBlock.gif
InBlock.gif         if(_bIsIE)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            evt = window.event;
InBlock.gif            src = evt.srcElement;
ExpandedSubBlockEnd.gif        }
InBlock.gif         else
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            evt = theEvent;
InBlock.gif            src = evt.target;            
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif         if(_mouseCapturedElement != src || evt.button == 2)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            _mouseCapturedElement =  null;
InBlock.gif             return;
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif        src = getPingElement(src);
InBlock.gif         if(src ==  null)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif             return;
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif         if(AllowParallelNavigation(evt, src))
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            _img =  new Image();
InBlock.gif            _img.src = src.attributes["gping"].value;
InBlock.gif             return  true;
ExpandedSubBlockEnd.gif        }
InBlock.gif        
InBlock.gif        _clickedAnchor = src;
InBlock.gif
InBlock.gif         if(_bIsIE)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            evt.returnValue =  false;
ExpandedSubBlockEnd.gif        }
InBlock.gif         else
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            evt.preventDefault();    
ExpandedSubBlockEnd.gif        }
InBlock.gif        doPing(src.attributes["gping"].value);
InBlock.gif
InBlock.gif         return  false;
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function AllowParallelNavigation(evt, src)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         var retVal =  false;
InBlock.gif         if(src.attributes["target"] && src.attributes["target"].nodeValue == "_blank")
InBlock.gif            retVal =  true;
InBlock.gif        
InBlock.gif         //  new window
InBlock.gif
         if(evt.shiftKey ==  true)
InBlock.gif            retVal =  true;
InBlock.gif        
InBlock.gif         //  new tab
InBlock.gif
         if(evt.ctrlKey ==  true)
InBlock.gif            retVal =  true;
InBlock.gif            
InBlock.gif         // middle mouse button
InBlock.gif
         if(evt.button == 4)
InBlock.gif            retVal =  true;
InBlock.gif
InBlock.gif         return retVal;
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function getPingElement(src)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         var retVal = src;
InBlock.gif         var bHasPing = hasPing(src);
InBlock.gif
InBlock.gif         while( bHasPing ==  false )
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            src = src.parentNode;
InBlock.gif             if(src ==  null)
ExpandedSubBlockStart.gif ContractedSubBlock.gif             dot.gif{
InBlock.gif                retVal = src;
InBlock.gif                 break;
ExpandedSubBlockEnd.gif            }
InBlock.gif
InBlock.gif            bHasPing = hasPing(src);
InBlock.gif
InBlock.gif             if(bHasPing)
ExpandedSubBlockStart.gif ContractedSubBlock.gif             dot.gif{
InBlock.gif                retVal = src;
InBlock.gif                 break;
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
InBlock.gif         return retVal;
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     //  FF was not behaving properly in the terse version of this check
InBlock.gif
     function hasPing(node)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         var retVal =  false;
InBlock.gif        
InBlock.gif         if(node.attributes)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif             if(node.attributes["gping"])
InBlock.gif                retVal =  true;
ExpandedSubBlockEnd.gif        }
InBlock.gif
InBlock.gif         return retVal;
ExpandedSubBlockEnd.gif    }
InBlock.gif    
InBlock.gif    
InBlock.gif     function doPing(payload)
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif        _img =  new Image();
InBlock.gif        
InBlock.gif        bind_method(_img, "load", onPingComplete,  false);
InBlock.gif        _img.src = payload;
InBlock.gif       _timer = setTimeout(onPingComplete, TIMEOUT);
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function onPingComplete()
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif        _img =  null;
InBlock.gif
InBlock.gif        resetTimeout();
InBlock.gif        doNav();
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function resetTimeout()
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         if(_timer)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif            clearTimeout(_timer);
InBlock.gif            _timer =  null;
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function doNav()
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{
InBlock.gif         if(_clickedAnchor)
ExpandedSubBlockStart.gif ContractedSubBlock.gif         dot.gif{
InBlock.gif             if( _bIsIE )
ExpandedSubBlockStart.gif ContractedSubBlock.gif             dot.gif{
InBlock.gif                _clickedAnchor.click();
ExpandedSubBlockEnd.gif            }
InBlock.gif             else
ExpandedSubBlockStart.gif ContractedSubBlock.gif             dot.gif{
InBlock.gif                 var clicker = document.createEvent("MouseEvents");
InBlock.gif                clicker.initEvent("click",  truetrue);
InBlock.gif                _clickedAnchor.dispatchEvent(clicker);
ExpandedSubBlockEnd.gif            }
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
InBlock.gif
InBlock.gif     function onUnload()
ExpandedSubBlockStart.gif ContractedSubBlock.gif     dot.gif{    
InBlock.gif        unbind_method(document.body, "mouseDown", onMouseDown,  false);
InBlock.gif        unbind_method(document.body, "mouseup", onMouseUp,  false);
InBlock.gif        unbind_method(window, "unload", onUnload,  false);
ExpandedSubBlockEnd.gif    }
ExpandedBlockEnd.gif}

    // 神啊,救救我吧!Google就用了10来行代码,还做了浏览器兼容

    算了,这事儿就当微软的程序员写代码效率高,一袋烟的功夫就是近200行。Live中Image访问的地址是:/GLinkPing.aspx?/_1_9SE/1?http://yyq123.wordpress.com/2006/04/&& DI=6244& IG=31498446f2a144f6993cd513bf80c39a& POS=1& CM=WPU& CE=1& CS=AWP& SR=1& sample=0,其中那个IG应该是个GUID,由于Live还回传了该被点击页面的URL(http://yyq123.wordpress.com/2006/04/),所以那个IG可能是关键字标识。最后看看这个Image的返回结果,没有想到微软还真的把这个请求当了回事儿,给浏览器返回了一个gif图片@_@:

None.gifHTTP/1.1 200 OK
None.gifContent-Length: 42
None.gifContent-Type: image/gif
None.gifX-Powered-By: ASP.NET
None.gifP3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND", policyref="http://privacy.msn.com/w3c/p3p.xml"
None.gifX-TraceID: 056743472244460c8331da7eeea643bd
None.gifExpires: Sat, 09 Dec 2006 21:17:51 GMT
None.gifCache-Control: max-age=0, no-cache, no-store
None.gifPragma: no-cache
None.gifDate: Sat, 09 Dec 2006 21:17:51 GMT
None.gifConnection: keep-alive
None.gif
None.gifGIF89a

    // 也就42个字节的gif图片,要是一直缓存在内存中可能也没啥吧

    Yahoo收集方案:火星、低效
    Yahoo-ABIS.png
    // 这样的导航方式,目前只有在广告中使用使用的比较多,能保证对点击计数

    这种很火星的方式用在这里还很低效,因为每次访问结果连接都需要进行重定向。结果条目连接为:<class=yschttl  href="http://rds.yahoo.com/ _ylt=A0geuphiK3tF4eEAwClXNyoA; _ylu=X3oDMTE2ZHNkdThpBGNvbG 8DZQRsA1dTMQRwb3MDMQRz ZWMDc3IEdnRpZANFMjY2Xzk3/ SIG=12mo7os6g/ EXP=1165786338/** http%3a//www.microsoft.com/china/sql/solutions/bi/solution/usoft.asp">极光商智商务智能解决方案</a>比如当我们点击了第一个条目:http://rds.yahoo.com/ _ylt=A0geuphiK3tF4eEAwClXNyoA; _ylu=X3oDMTE2ZHNkdThpBGNv bG8DZQRsA1dTMQRwb3MDMQRzZW MDc3IEdnRpZANFMjY2Xzk3/ SIG=12mo7os6g/ EXP=1165786338/  **http%3a//www.microsoft.com/china/sql/solutions/bi/solution/usoft.asp后,首先会访问yahoo.com的rds子站点,rds应该就是redirect server的缩写。由于使用redirect,用户浏览器就会进行跳转,所以效率很低。而且点击连接后,跳转到实际目的页面的成败和速度,和rds服务器的状态和响应速度关系很大。

    访问该连接后返回的结果为:

None.gifHTTP/1.1 302 Found
None.gifDate: Sat, 09 Dec 2006 21:50:48 GMT
None.gifCache-Control: private, max-age=0, no-cache
None.gifP3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
None.gifLocation: http://www.microsoft.com/china/sql/solutions/bi/solution/usoft.asp
None.gifConnection: close
None.gifContent-Type: text/html
None.gif
None.gifThe document has moved  < HREF ="http://www.microsoft.com/china/sql/solutions/bi/solution/usoft.asp" >here </ A >. < P >
None.gif <!--  rd6.search.mud.yahoo.com uncompressed Sat Dec  9 13:50:48 PST 2006  -->


    注意最后两行,是html正文。当用户浏览器不支持Location参数所设置的redirect操作时,浏览器就会显示一个连接,需要用户再次点击才能访问目的页面。所以说Yahoo的这个方法,确实是火星又低效!

    Baidu收集方案:给钱了吗?
    Baidu-ABIS.png

    
    Baidu对用户通过它的结果得到了什么结果是不关心的,其结果条目为:<href="http://bi.u-soft.com.cn/Products/analysis_report/" target="_blank">分析和报表概览 - 宏信极光商智</a>,非常简陋一个link。因为baidu的搜索结果排名是可以用钱来买的,所以baidu也没有必要关心到底用户希望什么结果尽量靠前出现。但是baidu对用户关心的东东也还是有兴趣的。在搜索结果页面中,baidu单独对用户关键字进行了采集,访问的地址是:http://c.baidu.com/c.gif? t=0& q=%22%BC%AB%B9%E2%C9%CC%D6%C7%22& p=0& pn=1。因为baidu需要把搜索频率高的关键字卖给广告用户,所以这个统计是必须要的。而对于有助于提高检索效果的用户Clicked Pages统计,似乎就无关紧要了。

    另外,其实Baidu对Yahoo使用的那种火星提交方式还是会的,不过只用在了广告链接上面:
    Baidu-BI-AD.png
    // 这3个搜索结果中的广告,使用了Yahoo那种Clicked Page提交方式

    这种广告链接的跳转实现和Yahoo基本一样,只是返回的结果稍有区别。Baidu返回的结果是:

None.gifHTTP/1.1 302 Found
None.gifDate: Sat, 09 Dec 2006 22:46:31 GMT
None.gifServer: apache 1.0.1.0/apache 1.3.34 (Unix)
None.gifSet-Cookie: shifen[12759223]=1165704391
None.gifLocation: http://www.hyperion.com/cn/products_bi.cfm
None.gifPragma: no-cache
None.gifConnection: close
None.gifTransfer-Encoding: chunked
None.gifContent-Type: text/html
None.gif
None.gif0


    这样一来,如果你的浏览器不支持Location指定的跳转,你居然连想看个广告都很难。另外虽然你没有看到这个你点击的广告,但是作为按点击付费的冤大头广告主还是需要掏钱的emdgust.gif

本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8月前
|
存储 NoSQL 搜索推荐
Redis地理位置和搜索:实现位置服务和简单搜索引擎
本篇深入研究了Redis的地理位置数据类型及其应用,以及如何基于Redis构建一个简单的搜索引擎。我们首先介绍了地理位置数据类型(Geo),展示了如何使用它来存储位置信息,并进行位置查询、距离计算以及附近位置搜索。通过代码示例,读者可以了解如何利用地理位置数据类型实现位置服务。
322 0
|
4月前
|
前端开发 JavaScript 应用服务中间件
百度搜索:蓝易云【服务器如何配置支持history模式】
配置完毕后,服务器将会将所有请求重定向到你的应用的index.html文件,使得history模式能够正常运行。这样,当用户在浏览器中直接访问子路径时,服务器会正确地返回index.html,并由前端路由接管处理。
62 1
|
5月前
|
存储 SQL 缓存
百度搜索:蓝易云【uniapp本地存储详解】
综上所述,UniApp提供了本地缓存和本地数据库两种本地存储方式,可以根据需求选择适合的方式来存储和操作数据。
348 8
|
8月前
|
数据采集 搜索推荐 安全
谷歌搜索留痕快速收录怎么实现?
答案是:通过GPC爬虫池技术实现的。 在搜索引擎优化(SEO)领域,快速收录是许多网站主人追求的目标。 而在谷歌搜索引擎中,搜索留痕快速收录成为了一种重要的实现途径。 以下内容详细介绍了如何实现谷歌搜索留痕快速收录。
106 0
谷歌搜索留痕快速收录怎么实现?
|
9月前
做了一个电驴 p2p资源搜索小软件
做了一个电驴 p2p资源搜索小软件
82 0
|
小程序 数据可视化 定位技术
小程序云开发实现根据地理位置范围内搜索数据
小程序云开发实现根据地理位置范围内搜索数据
137 0
小程序云开发实现根据地理位置范围内搜索数据
|
搜索推荐 UED
影响搜索排名的用户行为
可以影响排名的用户行为如下。 1.网站流量和Alexa排名 这两个因素是最直接、误差最大的因素,其中Alexa排名因为其样本分布不均匀、容易作弊等特点,与网站真实流量往往有很大的误差,不过总体流量也是在一定程度上说明网站的受欢迎程度,因此这一类用户行为的总和也是在影响着排名的。
136 0