用镜头记录,用心灵体验 | 订阅本站 | 所有笔记 | 亲和力设计 | 流量

DB2 学习笔记

博客话题:DB2,Linux,Web,业余无线电,户外,摄影,截拳道,Thankpad,其他

Web

使用Javascript 高亮搜索引擎关键词

目录

  1. 需求
  2. Hilite
  3. 原理
  4. 功能扩展
  5. 中文支持
  6. 关键词链接索引
  7. 支持更多搜索引擎
  8. 搜索相关文章
  9. 便捷搜索
  10. 代码下载
  11. 参考资源
  12. 更新 2007-02-07

需求

很大一部分网站,搜索引擎是其最重要的外部访问来源,某些情况,用户宁愿在简洁的搜索页面敲入关键词,也不愿按照一条已知的访问路径来找到资源。如果你的页面很大,定位搜索的关键词会不太容易,并不是每个使用者都知道使用"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,同时做了以下功能扩展:

  1. 增加了对中文关键词的支持。
  2. 增加了对关键词的链接索引,可以通过锚点(anchor)迅速链接到关键词首次出现的地方。
  3. 增加了国内流行的搜索引擎,因为要分析refferer,所以针对每个搜索引擎需提供单独的代码。作者的程序结构非常好,所以很容易扩充。
  4. 增加了搜索站内相关文章的功能,不需要动态程序,只需要利用搜索引擎和Meta 标签,当然这也需要对网站页面进行更多的修改。
  5. 额外增加了一个微不足道的小功能,把用户搜索的关键词再次放到这个页面上,让用户可以快速的发起第二次搜索(可以是在你网站内部)。

中文支持

搜索时浏览器已将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 码取得对应字符,这里用作将GB2312编码的汉字ascii码还原为汉字。Javascript 语言使用Unicode 编码,未提供此函数。因此,我们须提前声明这个函数,这里将这个函数保存在一个单独的.vbs 文件中,并通过如下语句进行引用,供Javascript 调用。

<script type="text/vbscript" src="/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 中定义的关键词(如果定义了多个,只取前两个)提交到搜索引擎继续搜索。

要使用此功能,需要:

  • 修改参数refill2:
Keyword.refill2: true,
  • 修改参数element2:
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()'>站内相关文章&nbsp;&gt;</a>
</form>
<!-- Search Baidu -->

便捷搜索

要使用此功能,需要:

  • 修改参数refill1:
Keyword.refill1: true,
  • 修改参数element1:
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.

Alex's picture

my email address in picture

搜索|Search

评论|Recent Comments

按月归档|By Month

2009
07
2008
11
10
07
05
04
03
02
01
2007
12
10
07
06
05
04
03
02
01
2006
12
11
10
09
08
07
06
05
04
03
02
01
2005
11
10
09
08
07
04
03
2004
12
11
10
09
08
07
06
05
04
03
02
01
2003
12
10
09
08
06
2002
09
08
04
03
02
2001
12
09
07
06
05

我读|My Books

我的链接|My Links

我的朋友|My Friends

Creative Commons License
This blog is licensed under a Creative Commons License.
Movable Type 4 Logo