自定义"Google自定义搜索"

分类:应用接口| 发布:camnprbubuol| 查看: | 发表时间:2010/10/25

通常我们选用 Google CSE 自定义搜索引擎代替网站自身的搜索服务,可以减轻服务器的负载,但更重要的原因是 Google 搜索有强大的词语分割、智能匹配、拼写纠正功能,甚至能将 "bb" 与 "BlackBerry", "DM" 与 "桌面管理器" 进行通配,这些算法是我们自己做不到的。我以前在博客中采用 iframe 版的 CSE, 最近把它换成了定制性更强,基于 Google ajax API 的新版,将经验分享一下。本方案优点:

  • 不搜索时完全不加载任何相关资源,如 ajax API 库等
  • 搜索 url 非常干净,没有多余的参数:fis.io/search?q=cse
  • 方便使用 javascript 对结果样式进一步调整

获取代码

首先需要在 控制面板 - 外观新功能!中选择“搜索元素”模式 (Search element), 再选择一种布局和一种样式。实际上 ajax API 能做的事情非常多,比如就在搜索框下方即时展开结果列表。如果把结果列表悬浮绝对定位,再加上 Search as user Types, 就可以做 apple.com 右上角那种搜索样式了,一边输入一边匹配。

但是考虑到小博客的站内搜索被使用得并不多,我还是选择了两栏布局,将结果列表放在一个专门的页面 /search 中,这样的好处是不搜索的时候可以不加载多余的内容:API 库,JS, CSS 等等。

改造搜索框

先不急着把获取的那一大堆代码往搜索框上放,上面说了,我们要的效果是不搜索的时候不加载。就改造一下模板原生的搜索框就可以了,让它提交用户输入的内容到 /search 这个页面,就这样。我的 header.php 中的搜索框是这样的:

<form action="/search" id="searchbox">
    <input type="text" name="q" id="input_search" />
    <input type="submit" value="搜索" />
</form>

一个 form 中装一个输入框和一个按钮,关键内容是 action="/search" 和 name="q", 表示将会跳转到 /search?q=搜索的内容.

结果页面

建立一个页面 /search 来放入所有 CSE 代码。页面正文中放入 id="cse" 的 div, 搜索执行的时候脚本将会改写其中的内容。

<div id="cse">正在搜索...</div>

然后在页面任意位置,比如末尾,写入前面获得的两个 javascript 代码,一个是 ajax API 库 google.com/jsapi, 另一个是以 google.load 开头的一大串。还有些 CSS, 是前面获取代码的时候选择的一种样式。

但这时候还不会自动执行用户之前输入的搜索,要从 url 请求中把搜索词剥离出来,并执行。这里我用了 Kevin Yang 提供的方法,在 draw(’cse’) 一行后加入:

var match = location.search.match(/q=([^&]*)(&|$)/);
if(match && match[1]){
    var search = decodeURIComponent(match[1]);
    customSearchControl.execute(search);
}

现在这个搜索系统就可以正常工作了。下面是对脚本的进一步自定义,只逐条说明,不每次都写完整的代码,我会把完整的修改后的脚本放在本文末尾。如果今后代码发生变动,请自行查看我的 搜索结果页 源代码。

不加载 Google 的 CSS

如果要用自己网站的样式,最好是完全不加载 Google 的 CSS, 不然覆盖样式就有得写了。在 google.load 中加入 "nocss" : true 即可。

google.load(’search’, ’1’, {language : ’zh-CN’ , "nocss" : true });

无结果时显示的文字

由 setNoResultsString 控制,在无结果时将字串写入到 "正在搜索" 处。中文语言下缺省值为“无结果”

customSearchControl.setNoResultsString(’什么也没找到,请重试’);

结果每页条数

由 setResultSetSize 控制,可选参数为 FILTERED_CSE_RESULTSET 10条;LARGE_RESULTSET 8条;SMALL_RESULTSET 4条。

customSearchControl.setResultSetSize( google.search.Search.SMALL_RESULTSET);

是否在新标签中打开链接

由 setLinkTarget 控制,一般用到的就是 LINK_TARGET_BLANK 和 LINK_TARGET_SELF 两种。

customSearchControl.setLinkTarget( google.search.Search.LINK_TARGET_SELF);

搜索执行完毕后调用其它脚本

由 setSearchCompleteCallback 控制,这是一个相当灵活的命令,我这里用它来将搜索结果标题中的“老肥博客 » 非唠不可”去掉,不然每条标题后面都有这样一句,比较难看。这里我另外加载了 jQuery 来用,当然这不是必需的,如果没有需要就不用了。

customSearchControl.setSearchCompleteCallback(null, function() {
    $(’input.gsc-input’).select();
    $(’a.gs-title’).unwrap().wrap(’<h3></h3>’).each(function() {
        var title = $(this).html().replace(/\|.*/g, ’’);
        $(this).html(title);
    });
    $(’b:contains("...")’).contents().unwrap();
});

以上在 setSearchCompleteCallback 中执行了三个步骤:

  • 将焦点放到搜索框 input.gsc-input 中并全选文字;
  • 将搜索结果标题链接 a.gs-title 先去掉外面的一层 div, 再套在 <h3> 内(这样方便沿用全局 CSS 里面的标题样式),然后对每个标题链接读取内容,替换,写回去;
  • 将包含 "..." 的关键字高亮去掉 <b>;(Google 用 <b> 标示关键字,但不知为何 "..." 也都这样标记)

其它

我的搜索页面中还有一些脚本和样式,比如将 CSE 的搜索框伪装成模板原生的输入框,这样可以避免多次搜索的时候重复加载页面;从搜索框中取得当前关键字,写入到右侧提示区;等等,比较特殊,这里就不细写了,反正 Firebug 什么的都一眼看穿。

另外,前面提到 Kevin 的文章中有个技巧很不错,只让单篇文章出现在搜索结果中,排除掉翻页、标签等页面,像我用 .html 作为单篇文章的链接结构就很好办,直接在 CSE 控制面板中设置“包含的网站”为 fis.io/*.html, 就排除了其它形式的链接结构。

微博也是博客,我在 fis.io/*.html 之外还将 twitter.com/fisio/* 编入了索引,在搜索某些内容的时候会看到我的推也在搜索结果中。

最后是我的 /search 页面中相关脚本完整版:

<script src="upload/2012/3/201203231357594114.gif" class="wp-smiley sm-sad">  什么也没找到,请重试’);
    customSearchControl.setSearchCompleteCallback(null,function() {
        $(’input.gsc-input’).select();
        var searchwords = $(’input.gsc-input’).val();
        $(’.p > b’).text(searchwords);
        $(’a.gs-title’).addClass(’new’).unwrap().wrap(’<h3></h3>’).each(function() {
            var title = $(this).html().replace(/\|.*/g, ’’);
            $(this).html(title);
        });
        $(’b:contains("...")’).contents().unwrap();
        $(’.gsc-cursor-current-page’).removeClass(’gsc-cursor-page’);
    });
    customSearchControl.draw(’cse’);
    var match = location.search.match(/q=([^&]*)(&|$)/);
    if(match && match[1]){
        var search = decodeURIComponent(match[1]);
        customSearchControl.execute(search);
    }
});
</script>

参考文献

365据说看到好文章不转的人,服务器容易宕机
原创文章如转载,请注明:转载自郑州网建-前端开发 http://camnpr.com/
本文链接:http://camnpr.com/api/64.html