锁定老帖子 主题:淘宝网的搜索关键字的编码与解码
该帖已经被评为良好帖
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
最后修改:2010-02-03
lichd 写道
刚刚看到你对淘宝编码的研究,我个人认为淘宝那个编码可能是Base32规范的演化版,只不过淘宝使用0来代替=做末位填充,RFC 3548 (The Base16, Base32, and Base64 Data Encodings)
对这些都有规范 经过证实,lichd 的观点正确,由于我在本文发表之前,除Base64 之外,其他的BaseXX 都没接触过,所以不知道这个正是Base32 的效果。
不过看官们请放心,本文的思路也和Base32 符合。当时的乱打乱撞,结果造了一个古人已经造好的轮子,实在惭愧。
因此,感谢lichd 的观点,从而稀释了我体内SB细胞的浓度。
回头看了一下本文的一个旧实现(codec.zip ),一年前写得代码太糟糕了,不推荐。 现在提供一个相对不错的实现,>>猛击获取<< 。
-------------------------- -------------------------- -------------------- --------------------- ------------------------------------------分割线 -------------------------------------------- -------------------------- -------------------------- -------------------- ---------------------
很久之前发现淘宝网的搜索关键字在编码后有点可爱,小写英文字母+数字的组合。 想去研究一下,但是后面好像没了回事似的。。记性不好 然后这两天不知道为什么,突然间抽起条脑筋,跑去研究。。。。
--------------------------开始分割线--------------------------
在淘宝网上用关键字“gembler”搜索一下商品,得出以下URL:
http://search1.taobao.com/browse/0/n-0-----------------g,m5sw2ytmmvza----------------40--commend-0-all-0.htm?at_topsearch=1 (留意上面这里:“m5sw2ytmmvza” )
经过一轮 天昏地暗、沙尘滚滚 的分析、研究之后,得出以下结论:
在Base64中,码表是由 [A-Z,a-z,0-9,+,/,=(pad)] 组成的。
-------------------------------愚蠢分割线---------------------------------
但是,世事往往不如人意,位数不够,那咋办呢?看下面 :)
但是,
按5位来分
割
,前面3个0是补定的了,后面的0就看上帝怎么安排了。
OK!又见回"aaa"了。 :)
搞了半天,“可视化编辑器”的 Java Code不好使,骨干代码在回帖里贴出................(完整的代码,有兴趣的同志们请见附件! )
--------------------------结束分割线--------------------------
。。。整理好了,整个人都铺满了灰尘.......
PS:不知道淘宝网的思路是不是这样
(补:另外一篇讨论 - “ 拍拍网的搜索关键字的编码与解码 ”) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
最后修改:2009-03-28
贴上部分代码片段
编码: /** * (编码/加密)字节数组 * * @author gembler * @version 2008-12-3 下午03:14:43 * * @param keyBytes * 需要(编码/加密)的字节数组 * * @return (编码/加密)后的字符串 */ private static String encode(byte[] keyBytes) { if (keyBytes == null || keyBytes.length < 1) { return ""; } /* * 合并二进制码, * 如: * 00101010 11010011 00101101 10100011 * to * 00101010110100110010110110100011 */ StringBuilder mergrd = new StringBuilder(); for (int i = 0; i < keyBytes.length; i++) { FormatUtil.formatBinary(keyBytes[i], mergrd); } /* * 以5个bit为单位,计算能分多少组, * 如: * 00101010110100110010110110100011 * to * 00101 01011 01001 10010 11011 01000 11 * | * (这个11为余下的位) */ int groupCount = mergrd.length() / FIVE_BIT; // 计算余下的位数 int lastCount = mergrd.length() % FIVE_BIT; // 类似数据分页的算法,有余数的情况下需要加 1。 if (lastCount > 0) { groupCount += 1; } /* * (编码/加密) */ StringBuilder sbEncoded = new StringBuilder(); // 循环所需的条件 int forMax = groupCount * FIVE_BIT; // 每次递增5位来截取 for (int i = 0; i < forMax; i += FIVE_BIT) { // 结束点 int end = i + FIVE_BIT; /* * 如果结束点比已合并的二进制码串的长度要大, * 相当于有余数, * 并且表示当前循环到了(已合并的二进制码串的长度 % FIVE_BIT)的那一截。 */ // 标记是否到了余数的那一截 boolean flag = false; if (end > mergrd.length()) { /* * 如果结束点比已合并的二进制码串的长度要大, * 结束点需要被重设为: * 已合并的二进制码串的长度,等价于(i + lastCount). 并且重设标记。 */ end = (i + lastCount); flag = true; } // 截取 String strFiveBit = mergrd.substring(i, end); // 截取后从二进制转为十进制 int intFiveBit = Integer.parseInt(strFiveBit, BINARY); if (flag) { /* * 如果结束点比已合并的二进制码串的长度要大, * 或者是到了余数的那一截: * 需要左移操作,假设余下的二进制位为:11, * 那么需要从后面补0,左移操作后为 (000)11(000) */ intFiveBit <<= (FIVE_BIT - lastCount); } // 利用该十进制数作为码表的索引获取对应的字符,并追加到sbEncoded sbEncoded.append(CODEC_TABLE.charAt(intFiveBit)); } return sbEncoded.toString(); } 解码: /** * (解码/解密)字符串 * * @author gembler * @version 2008-12-3 下午03:15:00 * * @param code * 需要(解码/解密)的字符串 * @param characterSet * 字符集 * * @return (解码/解密)后的字符串 */ public static String decode(String code, String characterSet) { if (code == null || code.length() < 1) { return ""; } /* * 拆除每一个字符,从码表里获取相应的索引。 */ StringBuilder sbBinarys = new StringBuilder(); for (int i = 0; i < code.length(); i++) { // 从码表里获取相应的索引 int index = getCodecTableIndex(code.charAt(i)); // 将十进制的索引转换为二进制串 String indexBinary = Integer.toBinaryString(index); // 去掉前3个0,并且追加到sbBinarys FormatUtil.formatBinary(indexBinary, sbBinarys, FIVE_BIT); } /* * 按8个bit拆分,剩下的余数扔掉。 * 扔掉的余数是在(编码/加密)的分割时候,在分剩的余数的后面补的0 */ byte[] binarys = new byte[sbBinarys.length() / EIGHT_BIT]; for (int i = 0, j = 0; i < binarys.length; i++) { // 每8个bit截取一份 String sub = sbBinarys.substring(j, j += EIGHT_BIT); // 将截取下来的二进制串转换为十进制 Integer intBinary = Integer.valueOf(sub, BINARY); binarys[i] = intBinary.byteValue(); } String decoded = null; if (characterSet == null || characterSet.length() < 1) { // 采用默认语言环境的 character set。 decoded = new String(binarys); } else { try { // 采用指定的 character set。 decoded = new String(binarys, characterSet); } catch (UnsupportedEncodingException e) { decoded = new String(binarys); } } return decoded; } 测试: BufferedReader br = new BufferedReader(new InputStreamReader( System.in)); while (true) { System.out.print("输入字符号串:"); String in = br.readLine(); if ("exit".equalsIgnoreCase(in)) { break; } String enCode = Codec.encode(in); String deCode = Codec.decode(enCode); System.out.println(); System.out.println("original: " + in); System.out.println("encode: " + enCode); System.out.println("decode: " + deCode); System.out.println(); } 测试结果: 输入:JavaEye论坛频道 输出: original: JavaEye论坛频道 encode: jjqxmykfpfs4fw6mwpdllnoa decode: JavaEye论坛频道 然后跑去淘宝网敲入"JavaEye论坛频道"搜索。 得出: http://search1.taobao.com/browse/0/n-g,jjqxmykfpfs4fw6mwpdllnoa----------------40--commend-0-all-0.htm?at_topsearch=1 比较一下: jjqxmykfpfs4fw6mwpdllnoa - console输出 jjqxmykfpfs4fw6mwpdllnoa - 淘宝网URL |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
以前也对这个问题有点兴趣,不过没细想过。
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
真是够强悍的!这都能分析出来!
少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
gembler 写道 netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' 嘿嘿,就因为这个? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
最后修改:2008-12-03
netfork 写道 gembler 写道 netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' 嘿嘿,就因为这个? 哈·这还是请淘宝网的研发人员回答吧···我纯粹兴趣研究 不过 '/' 这东西拼上URL就有点点问题,如果处理不当的话。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
gembler 写道 netfork 写道 gembler 写道 netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' 嘿嘿,就因为这个? 哈·这还是请淘宝网的研发人员回答吧···我纯粹兴趣研究 不过 '/' 这东西拼上URL就有点点问题,如果处理不当的话。 使用URLEncoder转一下不成吗? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
netfork 写道 gembler 写道 netfork 写道 gembler 写道 netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' 嘿嘿,就因为这个? 哈·这还是请淘宝网的研发人员回答吧···我纯粹兴趣研究 不过 '/' 这东西拼上URL就有点点问题,如果处理不当的话。 使用URLEncoder转一下不成吗? 如果关键字多一点,转出来就又长又臭了,不好看 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2008-12-03
gembler 写道 netfork 写道 gembler 写道 netfork 写道 gembler 写道 netfork 写道 少见多怪的问一句:淘宝为什么要对url进行Base64编码啊? 哈···其实我也不知道。。。 不过经过Base64后,可能会带有 '/' 嘿嘿,就因为这个? 哈·这还是请淘宝网的研发人员回答吧···我纯粹兴趣研究 不过 '/' 这东西拼上URL就有点点问题,如果处理不当的话。 使用URLEncoder转一下不成吗? 如果关键字多一点,转出来就又长又臭了,不好看 有道理!还是Base64转出来的看着顺眼些。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||