打造完美的 ajax 版 Google 自定义搜索
通常我们选用 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="https://www.google.com/jsapi" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
google.load('search', '1', {language : 'zh-CN' , "nocss" : true });
google.setOnLoadCallback(function(){
var customSearchControl = new google.search.CustomSearchControl('015811090669888844099:szzhafqj8_4');
customSearchControl.setResultSetSize(google.search.Search.SMALL_RESULTSET);
customSearchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
customSearchControl.setNoResultsString('<img src="/b.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>
图标比较可爱
肥叔叔,这篇文章写好,怎么没有特别通知我来抢沙发咩,我表示not happy
自己订阅…
咩。我的google reader 太汹涌了,又不是每天都看咩。。。 叔叔,我要special
http://feedburner.google.com/fb/a/mailverify?uri=fisio
这个够 special 了吧?
机器人 提醒木有情调
下次我记得的时候人肉提醒..
叔叔乖,奖励棒棒糖一只 (/ ̄ˇ ̄)/
你们有JQ,居然公开调情 哼哼
然后呢?
你是赤裸裸的嫉妒
嗯 Google自定义搜索添加到自己的博客上不错。。
嗯,找个时间也加到自己blog上去~~ 😛
诶?话说评论换成ajax的了?不错不错~~~~ 👍
哈哈,是啊
鼠标移到代码部分为什么要overflow:visible呢?文字破框而出了呀~
我觉得这样方便阅读些。。
今天把文章发出来才临时加上的 white-space: nowrap 和 overflow-x: auto, 回头再斟酌一下 😛
我觉得可以在hover的时候把<code>设为float:left
不过缺点是要紧跟清除浮动的标签,而且如果代码真的很长的话还是会有些问题
谢谢您的意见,float 这样好多了,边框一起变宽了。
我一开始就单独设了个 class 来做这个 hover, 就是担心以前文章里面的代码搞出问题,这样就不用去复查以前贴的代码了 😀
常规留言。。。看不懂
以前尝试过,没有成功!
不知道我这篇算写明白了没有 😀
好像挺有趣,回头试一下
哈哈。。
好,我去把我的搜索框修改一下,问题是,搜索框里面有个背景字啊,custom srearch,这个这么去掉啊,我看有点博客搜索框没这个字啊。
文中的方法加的输入框就是个普通的输入框,不是用的 google 的代码
研究一下,回头我也试试。
改改看上去爽多了
不错,支持一下
我看我有必要在我新主题内加上这功能。。。 8D
测试一下的!
楼层显示有点问题呀,都是1楼!
这个问题还没想到什么好的办法,不过反正刷新一下就是了…
你的主题很漂亮
给你的i[at]fls.io发邮件,是不是没收到啊?
问一下你的主题中,CSS中的当前页面(class:current_page)是如何把“存档”给做进去的?比如,点击你任一篇文章,都会发现,“订阅”页面被标记为当前页面,that’s
cool!这是如何实现的呢?谢谢。
我回复过了哈。。你mx什么的正常么,其它邮件收取是否正常?
哦,看到了……
忘记把Google Apps信箱的邮件转发到主信箱了……
呃。。。好吧
我现在都只用 google apps 邮箱了
另一个同名的 google account 没有 gmail 服务
我很喜欢你博客,很想要你所有的widget和代码,呵呵
抱歉,目前没有将修改版主题公布的打算..
似懂非懂看完了,等哪天再亲手实践一下
HOHO,不想在中国google已经完了
不会吧
不清不楚 看不明白
很完美!!!
老肥!我已经完全折服了。爱死您的博客了!
问下,链接上的箭头是什么插件?
那只是个 css 样式,应用于 a class=”external”, 有个右边的 padding, 然后应用了一个背景图片 😀
搜索结果标题怎么去掉博客的名称呀?
参考一下我的代码,就是这行:
var title = $(this).html().replace(/\|.*/g, ”);
将标题读取了之后,进行正则替换,扔掉了第一个 “|” 之后的所有内容,如果你的标题格式并不是这样,改成自己的就好了,| 前面的 \ 是转义符。
谢谢,这个问题解决了。
按照你的方法做了。为什么用IE和chrome搜索中文没有任何结果,而firefox下却正常呢?
这个比较奇怪了,仔细比较一下代码吧。。。
另外还有页面编码什么的也检查一下?
代码比较好几次了,如果我眼睛无码应该没问呀。我的博客不是放在根目录而是xx.com/blog/这样子的,是不是这个和那个正则表达“var match = location.search.match(/q=([^&]*)(&|$)/);”式有关系?
应该是这一步的原因,因为从你的搜索结果页面上的 google 搜索框去搜索中文是正常的.. 😮
试试看在 /q 之前加上 /blog 呢?
我测试了下,确定是子目录的问题,试着加/blog无效。这个该怎么修改呢?
我也是用的这个主题,请问怎么能实现评论框随着页面的往下而自动向下滚动 呢?
看本页的源代码,里面引用了 jquery, 还有一段代码是滚动用到的,源代码里搜索一下 toppadding 就找到啦
谢谢了
原来高手隐于市啊
我这里GOOGLE好像访问不了呀,郁闷 :O
留个名 这个博客做得太好了 🙂
继续支持老肥童鞋…顺便也跟进下新技术.
有意思! 👍
这不错啊 ,好东西,完了我也加上
看得有点迷糊!!!!
👍 测试成功了,哈哈,我用的PAGE的模板,可以看这里,样式就象这样:http://shengshengman.com/search?q=hello+site%3Ashengshengman.com
谷歌推出的很多有意思的插件,可惜被大陆屏蔽了,真是郁闷。。。
先看看,大家都用了我再玩。。
:)不错。。。
现在返回的结果最多只能有8页吗?上一页-下一页怎么做的?
翻页按钮是自带的,我只是调过了样式,如果有更多的搜索结果,好像是另外打开一个 google 的页面来显示,也可以关闭掉这个外链
Just for a test!
不错,学习了…
效果是不错啊
博客好热闹,留言真多,路过。。。。
真是强人
嗯,找个时间也加到自己blog上去~~~ 👍
都是技术方面的东西哦,我都看不懂。
谢谢了.是高手呀.
我按照博主的方法,发现只能搜索英文能同步到search页面,但是如果搜索中文,搜索的关键字就不行
这个问题我倒是没遇到,不过有个朋友遇到过,来问过我,后来好像他自己把问题解决了,不如你问问看他吧? http://www.badmilk.com.cn/blog/contact
您好,看了好多人做的Google自定义搜索,均没有完美解决问题,你的搜索看起来解决了许多问题,我研究了很久依然没成功,主要是样式的定义,无法控制外观,出现很多问题,可否把你的搜索的相关文件发到我QQ邮箱:394731189@qq.com
我好研究一下,非常感谢
样式和脚本都在页面源代码里面,到搜索页查看页面源代码就可以了
跟其他人一样,用中文传参数会报错:
解码的url不合法
解决方法是将页面编码变成utf-8
另外一个问题是,你试着用ie浏览器浏览下,就会发现,你的搜索框在输入一次内容之后缩小成只容一个字符那样的宽度,解决的方法是,在你的css文件中加入如下这行:
.gsc-input{width:155px;}
定义他的宽度。
其实还存在一个问题,你用ie浏览器搜索会发现,第一条搜索结果的标题没有显示,
我改了你自己定义的一些jQuery,我也不知道咋意思,不过这问题被我稀里糊涂的解决了。
博主,关注您博客很久了,可以和您做一个友情吗?
有时间我也要试下! 😀
其实还有个致命的漏洞,你在你的博客搜索
字母”b” 这个关键字看看
你再测试一下分页,你点下第七页,就会发觉
本来只有八页,现在变成了只有两页而已。请问博主,这个问题如何解决? 8)
这个问题也没多严重吧,而且估计也做不了什么
已经点阅!!
这篇文章不错.收藏一下.谢谢了!
不错。。支持
老肥是个非常有耐心,写得好仔细啊
江总书记,病句啊。。
非常感谢你的博客,我的项目完成了,大家可以看看我做的自定义搜索
http://www.nomoso.cn/search_new.php?action=class_ques&c=4
XD
感谢你的博客,我的项目也做完了,解决了很多问题,欢迎大家跟我讨论
这是我的Google自定义搜索
http://www.nomoso.cn/search_new.php?action=class_ques&c=4
哈哈哈,貌似评论重复了,因为我点第一次没反应,关于输入b翻页问题,其实是Google自己的问题,这问题我测试过了,的确是Google自己的问题,可能有人不相信Google这大公司也有这种错误,其实还有一个乱码的问题,Google自己的网站上也是出现这个问题。
确实是高手
这个不错,比iframe的可自定义的内容多了很多
博客更新的不错。支持
按老肥的教程做成功了,谢谢老肥,写的很仔细 👍
0.0。。评论框竟然是飘浮的。。飘浮啊。。
———-
热。。。
好文。另,评论框跟随很富想象力
测试一下啦 👍
这个自定义搜索有意思,而且也很漂亮
和我同在一个服务器的老肥。。。
很好的功能,正在思考博客里面的搜索框
准备弄弄
加上去了 XD
模板真漂亮~~!可惜我不太会CSS~
老肥这favicon看着眼熟……
那是。。哈哈
这个主题好让人眼馋啊,什么时候能发出来啊?[img]http://gif2show.appspot.com/smile/11.gif[/img]
忒厉害 订阅中
可惜我也不太会CSS~
刚整理了下收藏夹,若干年前收藏的博客吖
试一下回复
确实不错,不知道能不能加到cms上~
发现搜索后搜索框的长度会变短。
那是 IE6
喜欢google的产品
有时间也在自己的博客上试一下。毕竟自己的博客就是针对Google的技术的 😛
为什么我的最多只显示3页,难道单纯是索引的太少了? http://hotoo.github.com/blog/search.html
搜 google 有四页..
另外一个问题:搜索 vimwiki 第一页的时候显示有 3 页,但是翻页到后面,却只有两页。然后翻回到第一页还是 3 页。
这个,我也是这样。。
真不错
很不错
这个感觉好麻烦 想弄的来着。。。
你这个域名 叼
这么好的博客,我从你这至少都取得了2名访客的回访了。不知道您是不是最近过于太忙的缘故,最近您好像都不怎么更新文章了。
还不错哦
我很喜欢你博客,很想要你所有的widget和代码,呵呵
不错,感谢分享啊
支持下 呵呵
8) 🙁 ;D
👍 🎂
技术文,留个脚印,慢慢详读。
博主 2011 新年快乐~!
请问能否给出google adsense版本的搜索能功能呢?
动态的评论框,感觉不错~~~
学习改造中。
不知道为什么 我那只显示一条搜索信息。 郁闷死了 能指导下不。
有空摆弄下…
谢谢老肥的分享,这次博客改造正好用得上!
很少人用到博客上的搜索~~
很不错,收藏了! 😀
非常实用的文章
听说今天是纪念日
嗯
😛
你这个主题是我见过最强悍的了,哇,这个方法更爽,哈哈,偶像啊
有时候我在线我们的博客真的需要那么强大的搜索功能吗?我现在改用默认的了,懒得改模板
博主是技术党啊。这个个性搜索蛮实用的。支持下
有空试试 🙂
好久没更新文章啦?
好文章,原来谷歌搜索也有API
学习了 ;D
果然很好、
楼主域名也很棒啊
GOOGLE 提供的东西都那么好利用。 😀
这个评论框很好玩
博主这个留言板,太好了
博主,你是怎样去掉自定搜索再带的那个搜索框的?
不是去掉了自定搜索的搜索框,而是留了它,去掉了原来位置的那个
学习了!!!但请问有没有办法让出来的结果的链接不是通过google的url跳转阿?遇到敏感词时一跳转就被墙,貌似90秒左右
google 就是google,每样东西都很好用
要用到了,来看看这篇。
这真是技术型文章啊,赶紧折腾。
google cse最近改版了,作为新的趋势,希望博主能对这篇博文更新下
贵站现在用的是该文描述的方法吗?怎么搜索的时候不显示搜索结果呢?测试了 IE9 和 Chrome。
是的,但是搜索一切正常嘛
那看来是我的 IE9 出问题了,搜索之后没有结果显示。
刚又试了试 Firefox,倒是显示搜索结果了。
请教站长,为什么我按照以下步骤,都没有成功呢?
1.把“searchform”搜索框代码更改你上述的代码
2.建立 cse.php文件上传,并建立search页面【导入cse.php模板】,cse.php模板的代码是最后/search的完整版;
结果一点效果都没有。。。我不太懂代码,我上面这样的步骤有什么不对的吗?
对了,你的固定链接是怎么设置的?
麻烦站长答复,非常感谢!
为什么没有成功。。这个真回答不了,找个熟悉你代码的人帮你看吧。固定链接的设置在 WordPress 设置里有
谢谢博主的回答。
能否问2个和代码没有关的问题?
1.我的2个步骤没有出错吧?
2.除了你上述的步骤,还需要做其他设置吗?
呵呵,不好意思,再请教个非代码问题
是不是要申请Google AJAX Search API key,这些代码才能生效呢?
博主,你的博客文章都写得不错,怎么一直没有再更新了呢?
这个很好用啊
我仔细看了你写的,听着很高深的样子,然后,我试了一下你右上角的那个谷歌搜索,然后,,,然后一直等待。。。我重新刷新了页面,又欢乐个词搜索,然后,,,还是等待,,,
这个不是一般的复杂,我直接把GOOGLE的代码放上去就行了。
前來支持一下~~好多評論哇!! 8D
博主,我想知道,谷歌被墙,自定义搜索还能用吗
不知道,应该不能了吧
大牛,pansou也是用的ajax search,为什么他不会被墙呢,因为他调用的地址是ip,不是直接的谷歌域名。请问怎么实现。