短鏈(短地址、Short URL)


     短鏈接產生和流行得益於社交網絡的發展。短鏈接可以更方便的在網絡中傳播,避免超出字符限制,使得分享地址更加容易並且能夠統計此地址的訪問信息。

     下面是新浪微博API對短鏈接口的描述:http://open.weibo.com/wiki/API%E6%96%87%E6%A1%A3_V2#.E7.9F.AD.E9.93.BE

     我們最關心的是將一個長鏈接轉化成短鏈接,其他內容暫不關心。

     打開長了,鏈轉短鏈的內容。

     上面有URL,調用方式是GET方法,請求參數有三個:source、access_token、url_long,結合三個參數的說明,采用OAuth授權的方式,source不需要填寫,否則source是應用的AppKey;采用OAuth授權的方式,access_token必填,內容通過OAuth授權后獲得,否則不需要填寫。url_long是需要轉化的長鏈,必填。結合上面的內容,請求這個接口的典型格式有以下兩種,分別是OAuth授權方式和非OAuth授權方式:

https://api.weibo.com/2/short_url/shorten.json?source=AppKey&url_long=NeedConvertURL

https://api.weibo.com/2/short_url/shorten.json?access_token=OAuthContent&url_long=NeedConvertURL

     OAuth授權方式的研究自己看文檔吧http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E

     非授權方式只需要一個AppKey和被轉換的長鏈就可以了。Google以下可以獲取一大堆的AppKey,如果你沒有自己的應用也不想創建的話,而且這些AppKey有一個好處是用戶量非常大,對接口的訪問頻次限制較小,相當於沒有限制。

iphone新浪微博客戶端 App Key:5786724301

iPad新浪客戶端App Key:2849184197

Google.Nexus浪客戶端App Key:1206405345

周博通微博管家App Key:202088835

Weico App Key:211160679

     有了AppKey,下面測試以下獲取短鏈接吧:

https://api.weibo.com/2/short_url/shorten.json?source=5786724301&url_long=http://www.baidu.com

https://api.weibo.com/2/short_url/shorten.json?source=5786724301&url_long=http://www.baidu.com&url_long=http://www.sina.com.cn

 結果:

{"urls":[{"result":true,"url_short":"http://t.cn/h5mwx","url_long":"http://www.baidu.com","type":25}]}

{"urls":[

{"result":true,"url_short":"http://t.cn/h5mwx","url_long":"http://www.baidu.com","type":25},

{"result":true,"url_short":"http://t.cn/h5myh","url_long":"http://www.sina.com.cn","type":25}

]}

     返回結果中的url_short就是我們想要的內容。

     下面介紹短鏈接服務是如何實現的。

     所以短鏈接的原理很簡單:通過一個“方法”得到長鏈對應的一個字符串,與擁有的短域名拼接成一個地址,訪問這個地址的時候解析出原來的長鏈,然后跳轉。

     提供短鏈接首先必須要有一個足夠短的域名。顯而易見,將http://www.sina.com.cn轉化成http://myshorturl.com/xysmfd的意義並不大。可以看到新浪短鏈接所使用的域名是t.cn,這個真的是足夠短了(網易提供的短鏈接服務的域名是126.am),所以如果你想為別人提供短鏈接服務,你首先要申請到一個足夠短的域名。

     接着就是通過一些“方法”將傳入的長鏈轉換成一個類似於h5mwx這樣的結果,然后當訪問http://t.cn/h5mwx的時候找到h5mwx對應的長鏈,之后跳轉。

     目前網上查到的短鏈接多數都是按下面這篇文章的方式實現的。http://www.cnblogs.com/zhanghaoh/archive/2012/12/24/2831264.html

 1 package com.bjdata.test;
 2 
 3 import java.security.MessageDigest;
 4 import java.util.Random;
 5 
 6 
 7 public class ShortUrlTest {
 8     public static void main(String[] args) {
 9         String sLongUrl = "http://www.51bi.com/bbs/_t_278433840/"; // 原始鏈接
10         System.out.println("長鏈接:"+sLongUrl);
11         String[] aResult = shortUrl(sLongUrl);//將產生4組6位字符串
12         // 打印出結果
13         for (int i = 0; i < aResult.length; i++) {
14             System.out.println("[" + i + "]:" + aResult[i]);
15         }
16         Random random=new Random();
17         int j=random.nextInt(4);//產成4以內隨機數
18         System.out.println("短鏈接:"+aResult[j]);//隨機取一個作為短鏈
19     }
20 
21     public static String[] shortUrl(String url) {
22         // 可以自定義生成 MD5 加密字符傳前的混合 KEY
23         String key = "test";
24         // 要使用生成 URL 的字符
25         String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h",
26                 "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
27                 "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
28                 "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
29                 "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
30                 "U", "V", "W", "X", "Y", "Z"
31 
32         };
33         // 對傳入網址進行 MD5 加密
34         String hex = md5ByHex(key + url);
35 
36         String[] resUrl = new String[4];
37         for (int i = 0; i < 4; i++) {
38 
39             // 把加密字符按照 8 位一組 16 進制與 0x3FFFFFFF 進行位與運算
40             String sTempSubString = hex.substring(i * 8, i * 8 + 8);
41 
42             // 這里需要使用 long 型來轉換,因為 Inteper .parseInt() 只能處理 31 位 , 首位為符號位 , 如果不用long ,則會越界
43             long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);
44             String outChars = "";
45             for (int j = 0; j < 6; j++) {
46                 // 把得到的值與 0x0000003D 進行位與運算,取得字符數組 chars 索引
47                 long index = 0x0000003D & lHexLong;
48                 // 把取得的字符相加
49                 outChars += chars[(int) index];
50                 // 每次循環按位右移 5 位
51                 lHexLong = lHexLong >> 5;
52             }
53             // 把字符串存入對應索引的輸出數組
54             resUrl[i] = outChars;
55         }
56         return resUrl;
57     }
58     /**
59      * MD5加密(32位大寫)    
60      * @param src
61      * @return
62      */
63     public static String md5ByHex(String src) {
64         try {
65             MessageDigest md = MessageDigest.getInstance("MD5");
66             byte[] b = src.getBytes();
67             md.reset();
68             md.update(b);
69             byte[] hash = md.digest();
70             String hs = "";
71             String stmp = "";
72             for (int i = 0; i < hash.length; i++) {
73                 stmp = Integer.toHexString(hash[i] & 0xFF);
74                 if (stmp.length() == 1)
75                     hs = hs + "0" + stmp;
76                 else {
77                     hs = hs + stmp;
78                 }
79             }
80             return hs.toUpperCase();
81         } catch (Exception e) {
82             return "";
83         }
84     }
85 
86 }

     這個算法有值得改進的地方:

  1. 它最后為了62進制,使用的是0x0000003D,轉成二進制最后幾位是111101,表示62,用它進行與運算的話會屏蔽掉二進制表示時第二位為1的數,因此屏蔽掉了接近一半的內容(因為不是1就是0,所以屏蔽的1就相當於砍掉了一半,0-61中有30個數被看去),其實它是32進制了。
  2. MD5加密結果分為8位一組,最后產生4個短地址,這樣做重復的概率被大大提高了。32位中8位一組分4組后隨機選一組的概率出現相同的結果的概率遠大於32位MD5結果重復的概率。

     對於上面的兩個問題,我覺得是否可以使用64進制,如果計算出的結果是62、或者63,則隨機取一個數組中的值解決0x0000003D引起的問題;第二個一次提供四個短地址是否是為了出現重復的情況下重新選擇呢?

     希望看到這篇博客的博友們能給點自己的思路,如果能提供Google的短地址或新浪的短地址實現的方法就更好了(他們提供的短地址好像重4位-7位的樣子,不會是一個sequence轉成62進制吧?!)。

(在一篇博文中看到博主說他在網上看到這個算法是C#版的,將它翻譯成Java版,我還是挺欣賞的,畢竟人家思考了,寫了自己的東西。但就這么一段內容,好多“原創”博文,都不著名出處,也沒有自己的思考……誒……)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM