需求 很大一部分网站,搜索引擎是其最重要的外部访问来源,某些情况,用户宁愿在简洁的搜索页面敲入关键词,也不愿按照一条已知的访问路径来找到资源。如果你的页面很大,定位搜索的关键词会不太容易,并不是每个使用者都知道使用"Ctrl+F",如果能将这些关键词高亮显示,是个很好的主意。 当用户在Google 中使用“db2 学习笔记”作为关键词进行搜索时,如果你的网页列在了结果中,用户点开你的网页,页面中所有出现"db2" 和"学习笔记" 地方,都使用特殊的底色进行了标识。 Hilite 我在Scott Yang 的网站,看到了Search Engine Highlight Javascript ,使用他编写的程序:se_hilite.js 1.1 ,可以很轻松的在网站实现以上功能。 安装很简单,将se_hilite.js 保存在网站目录,并在每一个需要高亮关键词的网页中引用这个js...
需求
很大一部分网站,搜索引擎是其最重要的外部访问来源,某些情况,用户宁愿在简洁的搜索页面敲入关键词,也不愿按照一条已知的访问路径来找到资源。如果你的页面很大,定位搜索的关键词会不太容易,并不是每个使用者都知道使用"Ctrl+F",如果能将这些关键词高亮显示,是个很好的主意。
当用户在Google 中使用“db2 学习笔记”作为关键词进行搜索时,如果你的网页列在了结果中,用户点开你的网页,页面中所有出现"db2" 和"学习笔记" 地方,都使用特殊的底色进行了标识。
Hilite
我在Scott Yang 的网站,看到了Search Engine Highlight Javascript ,使用他编写的程序:se_hilite.js 1.1 ,可以很轻松的在网站实现以上功能。
安装很简单,将se_hilite.js 保存在网站目录,并在每一个需要高亮关键词的网页中引用这个js 文件:
<script type="text/javascript" xsrc="se_hilite.js"></script>
之后在CSS 样式单中加入如下定义:
.hilite { background-color: #ff0; }
如果在se_hilite.js 中设定了:
Hilite.style_name_suffix: true;
则还需要定义额外的CSS 样式:
.hilite1 { background-color: #ff0; }
.hilite2 { background-color: #f0f; }
.hilite3 { background-color: #0ff; }
.hilite4 ...
原理
如果在A 页面点击链接到达B 页面,则在B 页面可通过document.refferer 读到A 页面的链接。如果A 页面是一个搜索结果页面,则在B 页面读到的refferer 看起来会像下面这个样子:
http://www.google.com/search?q=db2+%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&hl=en&lr=&newwindow=1
通过解析这个链接,取出每一个关键词,并在B 页面装载完成之后,使用Javascript 对页面进行搜索,对每一个关键词位置加入描述底色的代码。
这个动作实际是在用户的客户端浏览器中完成的,并没有对你的实际网页内容做任何更改。
功能扩展
笔者下载并在网站安装了Hilite,同时做了以下功能扩展:
- 增加了对中文关键词的支持。
- 增加了对关键词的链接索引,可以通过锚点(anchor)迅速链接到关键词首次出现的地方。
- 增加了国内流行的搜索引擎,因为要分析refferer,所以针对每个搜索引擎需提供单独的代码。作者的程序结构非常好,所以很容易扩充。
- 增加了搜索站内相关文章的功能,不需要动态程序,只需要利用搜索引擎和Meta 标签,当然这也需要对网站页面进行更多的修改。
- 额外增加了一个微不足道的小功能,把用户搜索的关键词再次放到这个页面上,让用户可以快速的发起第二次搜索(可以是在你网站内部)。
中文支持
搜索时浏览器已将URI 进行编码处理,根据页面所采用的字符集不同,编码结果也不同。对于同一个关键词“db2 学习笔记”,Google(UTF-8) 和Baidu(GB2312) 的页面分别会产生不同的编码:
http://www.google.com/search?hl=en&q=db2+%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0
http://www.baidu.com/s?wd=db2+%D1%A7%CF%B0%B1%CA%BC%C7&cl=3
Javascript 中相应提供了用于解码的函数:
decodeURI(encodedURIString)
decodeURIComponent(encodedURIString)
上述decode 函数只能处理UTF-8 编码的URI,如果把GB2312 编码的URI作为参数,会抛出一个错误:
The URI to be decoded is not a valid encoding
我们必须自己实现一个处理GB2312 编码URI 的函数。
Keyword.decodeGBURI = function(strcode) {
try {
var result = '';
for ( var i = 0; i < strcode.length; i ++) {
var thischr = strcode.substr(i,1);
if (thischr == '%') { // 则后面为16进制编码
var ascii = eval('0x' + strcode.substr(i+1,2)); // 取出2位16进制值,转成10进制ascii码
if ((ascii > 0x20 && ascii < 0x30) ||
(ascii > 0x39 && ascii < 0x41) ||
(ascii > 0x5a && ascii < 0x61) ||
(ascii > 0x7a && ascii < 0x91)) { // !"#$%&'()*+,-./ :;<=>?@ [\]^_;` {|}~
try {
result = result + String.fromCharCodeAt(ascii); // 还原为单字节字符
} catch (e) { // ie6不支持,放弃,继续处理
i = i + 2;
continue;
}
i = i + 2;
} else { // 双字节字符
ascii = eval('0x' + strcode.substr(i+1,2) + strcode.substr(i+4,2)); // 取出4位16进制值,转成10进制ascii码
try {
result = result + chrval(ascii); // 还原为双字节字符,调用vb函数处理gb2312编码
} catch (e) { // 不支持vb脚本,放弃这个双字节字符,继续处理下面
i = i + 5;
continue;
}
i = i + 5;
}
} else if (thischr == '+')
result = result + ' '; // 加号还原为空白
else // 字母,不需要解码
result = result + thischr;
}
} catch(e) { return false; };
return result;
};
这个函数由Javascript 编写,但为了完成转换,额外调用了一个自定义的VBscript 函数chrval(vstrin) :
function chrval(vstrin)
chrval = chr(vstrin)
end function
函数chr() 根据ASCII 码取得对应字符。Javascript 语言使用Unicode 编码,未提供此函数。因此,我们必须将这个函数保存在一个单独的.vbs 文件中,并通过如下语句进行引用,供Javascript 调用。
<script type="vbscript" xsrc="/js/chr.vbs"></script>
关键词链接索引
如果希望打开此功能,需要设定:
Keyword.index: true,
对应实现此功能,增加了函数:
Keyword.indexHTML = function(html, query) {
var re = new Array();
var q = '您的查询关键词标明如下,点击可以跳到文中首次出现的位置:';
for (var i = 0; i < query.length; i ++) {
if (query[i]) {
var classname = Keyword.style_name;
if (Keyword.style_name_suffix)
classname += (re.length==0?'':re.length);
re.push([new RegExp('('+query[i]+')', "gi"), classname]);
q += '<span class="' + classname + '">' + (query[i]).link('#kIdx' + i) + ' </span>';
}
}
var last = 0;
var tag = '<';
var skip = false;
var skipre = new RegExp('^(script|style|textarea)', 'gi');
var part = null;
var result = '';
while (last >= 0) {
var pos = html.indexOf(tag, last);
if (pos < 0) {
part = html.substring(last);
last = -1;
} else {
part = html.substring(last, pos);
last = pos+1;
}
if (tag == '<') {
if (!skip) {
for (var j = 0; j < re.length; j ++) {
part = part.replace(re[j][0], ''.anchor('kIdx' + j) + '$1');
}
} else
skip = false;
} else if (part.match(skipre)) {
skip = true;
} result += part + (pos < 0 ? '' : tag);
tag = tag == '<' ? '>' : '<';
}
result = q + '<p>' + result;
return result;
};
支持更多搜索引擎
不同的搜索引擎会产生不同结构的URI ,需要对其进行分析,确定解码函数(UTF-8 或者GB2312),并提取出关键词。因此,要实现某个搜索引擎关键词的高亮显示,在以下函数中增加相关搜索引擎定义即可:
Keyword.decodeReferrer(referrer)
搜索相关文章
原理:在每个网页中通过Meta 标签定义关键词,如果用户通过搜索引擎找到了页面A,那么将页面A 中定义的关键词(如果定义了多个,只取前两个)提交到搜索引擎继续搜索。
要使用此功能,需要:
Keyword.refill2: true,
Keyword.element2: 'w',
- 在页面中加入如下代码(以Baidu 为例),参数element2 的值应与搜索引擎用于提交关键词的文本框名称一致。
<!-- Search Baidu -->
<form name="baidu2" method="get" action="http://www.baidu.com/baidu">
<input name="tn" type="hidden" value="bds" />
<input name="cl" type="hidden" value="3" />
<input name="si" type="hidden" value="aiview.com" />
<input name="ct" type="hidden" value="2097152" />
<input id="w" name="w" type="hidden" size="34" maxlength="100" class="frame" />
<a xhref='javascript:document.baidu2.submit()'>站内相关文章 ></a>
</form>
<!-- Search Baidu -->
便捷搜索
要使用此功能,需要:
Keyword.refill1: true,
Keyword.element1: 'word',
- 在页面中加入如下代码(以Baidu 为例),参数element1 的值应与搜索引擎用于提交关键词的文本框名称一致。
<!-- Search Baidu -->
<form name="baidu" method="get" action="http://www.baidu.com/baidu">
<input name="tn" type="hidden" value="bds" />
<input name="cl" type="hidden" value="3" />
<input name="si" type="hidden" value="aiview.com" />
<input name="ct" type="hidden" value="2097152" />
<input id="word" name="word" size="34" maxlength="100" class="frame" value="wwf" tabindex="1" />
<input type="submit" value="站内搜索" class="buttonface" tabindex="2" />
</form>
<!-- Search Baidu -->
代码下载
Scott Yang 的原程序只有一个文件se_hilite.js 1.1 (24 October 2004) - latest ,笔者修改的版本包含2个文件:keywords.js 1.2.0 chr.vbs。
由于程序修改后,已经不仅是Highlight 的功能,因此更改了程序中对象的名称为Keyword 。
参考资源
更新 2007-02-07
优化了针对不同浏览器的onload 事件处理 ,使highlight 加载得更快。这里下载更新的keyword.js v1.30.