`
jolestar
  • 浏览: 195395 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

搜索引擎URI编码的处理

阅读更多

做一个站内搜索遇到一个问题:

网站全站使用的是UTF-8编码,所以get请求的URL也用UTF-8编码,服务器端用UTF-8解码。这种情况下,用户直接在表单里输入提交过来搜索,是没有问题的。但如果用户直接在浏览器地址栏里把关键词给改了,提交过来,或者从浏览器地址栏的下拉提示列表里点击过来,URL编码就不确定了。这个和操作系统语言以及浏览器相关。

 

ie默认情况下,对在地址栏里输入的URL路径里的中文是用utf-8编码的,但对get参数不会自动编码,会直接把原始字符串发过去。

其他浏览器都会对地址栏里输入的get参数进行编码,编码方式和操作系统环境语言相关。

 

 

研究了一下几个大的搜索引擎是怎么处理这个问题的。

 

1.百度,搜狗等国内搜索引擎

这些搜索引擎的默认编码都是gb2312的,所以一般用户不会遇到这种问题。但我的系统是linux,系统编码是zh_CN.UTF-8的,就会遇到这种问题。

 

如百度:

gb2312编码:

http://www.baidu.com/s?wd=%D6%D0%B9%FA

utf-8编码

http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD

 

所以国内的搜索引擎基本没处理这个问题。应该认为这样的用户比较少,可以不予考虑吧。

 

2. google.com

google.com默认编码是utf-8,也只接受utf-8编码的地址,否则会出现乱码。google.com面对的是全球用户,不会专门为了中国用户而做特殊处理,可以理解。

gb2312

http://www.google.com/search?q=%D6%D0%B9%FA

utf-8

http://www.google.com/search?q=%E4%B8%AD%E5%9B%BD

 

3.google.cn

google.cn的默认编码也是utf-8。但它针对的是中文用户。而中文用户的大多数操作系统是中文的windows,浏览器的默认编码也一般是gb2312,所以这个问题必须考虑。google.cn能同时兼容两种编码。

gb2312:

http://www.google.cn/search?q=%D6%D0%B9%FA

utf-8:

http://www.google.cn/search?q=%E4%B8%AD%E5%9B%BD

 

google.cn是怎么做到的?

有人说数query里的%号,utf-8的一个汉字是3个字节,所以有三个%,而gb2312的编码的汉字是2个字节,2个%号。但遇到2和3的倍数呢?比方6个字节,是当3个gb2312的汉字处理呢还是2个utf-8的汉字处理呢?

 

 

于是在网上找了一下UTF-8的编码规则:

 

UTF-8的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的用x表示的二进制位,全部用这个符号的unicode码填充。

下表总结了编码规则,字母x表示可用编码的位。

    Unicode符号范围 | UTF-8编码方式
    (十六进制) | (二进制)
    --------------------+---------------------------------------------
   U-00000000 - U-0000007F: 0xxxxxxx  
   U-00000080 - U-000007FF: 110xxxxx 10xxxxxx  
   U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx  
   U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  
   U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx  
   U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

 

 

汉字的unicode符号范围是4e00-9fff(其中9FA6~9FFF还是空码),正好在第三行的范围内,也就是说每个汉字在UTF-8中都会转换为3个字节。其中第一个字节在11100000(0xE0)-11101111(0xEF)范围内,后两个字节在10000000(0x80)-10111111(0xBF)范围内。

 

于是办法产生了:

 

private static boolean isUTF8Query(String q)
	    throws UnsupportedEncodingException {
	byte[] bytes = q.getBytes("ISO-8859-1");
	for (int i = 0; i < bytes.length; i++) {
           //java 中的byte是有符号的,大于127的都为负数。先转换为int型正数再比较。
	    int first = 0x100 + bytes[i];
          //寻找查询关键词中的第一个中文字符的第一个字节
	    if (first < 0xE0 || first > 0xEF) {
		continue;
	    }
	    if (i + 2 < bytes.length) {
		int second = 0x100 + bytes[i + 1];
		int third = 0x100 + bytes[i + 2];
		if (second >= 0x80 && second <= 0xBF && third >= 0x80
			&& third <= 0xBF) {
		    return true;
		}
	    }
	}
	return false;
    }

 

 使用:

 

 

String q= request.getParameter("q");
q = isUTF8Query(q)?new String(q.getBytes("ISO-8859-1"),"UTF-8"):new String(q.getBytes("ISO-8859-1"),"GBK");
	

 

也有人用搜索queryString里的 %E 的个数的方式做这件事情。不过那样一方面不太准确,另一方面ie不会自动把用户在地址栏输入的get查询中的中文URLEncode,那样的情况下服务器端获取的queryString里没有%,

 

服务器端的问题:

 

用这种方式的时候,服务器端不能让服务器自动解码。如果是tocmat的话,在connector上不能设置URIEncoding="UTF-8",否则tomcat用utf-8解码后,再还原为原始字符串的字节比较麻烦。

如果是其他语言,比方php或者python,也不能让apache自动解码。

 

演示地址:

gb2312编码:

http://so.1ting.com/song.do?q=%C1%F5%B5%C2%BB%AA

utf-8编码:

http://so.1ting.com/song.do?q=%E5%88%98%E5%BE%B7%E5%8D%8E

 

地址栏里直接输入中文也可以。

 

 

 

 

 

2
0
分享到:
评论
5 楼 HYbdbc 2012-06-04  
貌似不能判断啊,我做了个测试,UTF-8编码的 还是显示gb2312
4 楼 jolestar 2009-05-12  
卡拉阿风 写道

所以自己加。

用户在浏览器地址栏里直接输入的东西你怎么给加?
3 楼 卡拉阿风 2009-05-11  
所以自己加。
2 楼 jolestar 2009-04-15  
卡拉阿风 写道

base64加密解密怎么样。而且比较美观
好处太多。。。

问题是浏览器不会自动给你加密啊。
1 楼 卡拉阿风 2009-04-14  
base64加密解密怎么样。而且比较美观
好处太多。。。

相关推荐

    URL编码转换器(C#源码)

    URL编码转换器,写搜索引擎时遇害到URI编码问题,顺手写了这个小软件~

    WEB渗透测试数据库

    pen.py的search子命令提供了Google Hacking的功能,目前支持以下搜索引擎: baidu bing google 例如: pen.py search "inurl:viewthread.php" -s 10 -o tmp.txt # --unique设定域名唯一,相同域名只记录一个...

    HTML开发王

    4.3.7 定义搜索引擎搜索方式 4.4 用于http消息报头的元数据(属性http-equiv) 4.4.1 设置网页内容类型和字符集 4.4.2 设置网页所使用的语言 4.4.3 设置网页定时跳转 4.4.4 设置网页禁用缓存 4.4.5 设置网页到期 4.4.6...

    javascript文档

    decodeURIComponent 方法 返回一个已编码的通用资源标识符 (URI) 组件的解码版。 递减运算符(--) 将变量减一。 delete 运算符 删除对象的属性,或删除数组中的一个元素。 description 属性 返回或设置关于指定...

    JScript 语言参考

    decodeURIComponent 方法 返回一个已编码的通用资源标识符 (URI) 组件的解码版。 递减运算符(--) 将变量减一。 delete 运算符 删除对象的属性,或删除数组中的一个元素。 description 属性 返回或设置关于指定...

    微软JavaScript手册

    decodeURIComponent 方法 返回一个已编码的通用资源标识符 (URI) 组件的解码版。 递减运算符(--) 将变量减一。 delete 运算符 删除对象的属性,或删除数组中的一个元素。 description 属性 返回或设置关于指定...

    精通ANDROID 3(中文版)1/2

    23.5 使用操作键和应用程序特有的搜索数据  23.5.1 在Android搜索中使用操作键  23.5.2 使用应用程序特定的搜索上下文  23.6 资源  23.7 对平板电脑的意义  23.8 小结  第24章 文本到语音转换  24.1 ...

    精通Android 3 (中文版)2/2

    23.5 使用操作键和应用程序特有的搜索数据  23.5.1 在Android搜索中使用操作键  23.5.2 使用应用程序特定的搜索上下文  23.6 资源  23.7 对平板电脑的意义  23.8 小结  第24章 文本到语音转换  24.1 ...

    java 面试题 总结

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...

    超级有影响力霸气的Java面试题大全文档

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 13、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 14、...

    新版Android开发教程.rar

    • 集成的浏览器 基于开源的 WebKit 引擎 • 优化的图形库 包括定制的 2D 图形库, 3D 图形库基于 OpenGL ES 1.0 (硬件加速可选) • SQLite SQLite SQLite SQLite 用作结构化的数据存储 • 多媒体支持 包括常见的...

    freemarker总结

    JAVA模版引擎Freemarker常用标签(一) 1. if指令 这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下: &lt;#if condition&gt;... &lt;#elseif condition&gt;... &lt;#elseif condition&gt;......

Global site tag (gtag.js) - Google Analytics