如何建立URL縮短器?

我想建立一個URL縮短服務,您能夠在其中將長URL寫入輸入字段,而後該服務將URL縮短爲「 http://www.example.org/abcdef 」。 php

除了「 abcdef 」以外,還能夠有其餘任何六個字符串,包含az, AZ and 0-9 。 這使得56〜570億個可能的字符串。 java

個人方法: git

我有一個包含三列的數據庫表: github

  1. id,整數,自動遞增
  2. long,字符串,用戶輸入的長URL
  3. 簡短的字符串,縮短的URL(或僅六個字符)

而後,我將長網址插入表中。 而後,我將爲「 id 」選擇自動增量值,併爲其構建一個哈希值。 而後應將此散列插入爲「 short 」。 可是我應該創建什麼樣的哈希? 像MD5這樣的哈希算法建立的字符串太長。 我認爲我不使用這些算法。 自建算法也將起做用。 算法

個人點子: 數據庫

對於「 http://www.google.de/ 」,我獲得了自動增量ID 239472 。 而後,我執行如下步驟: app

short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.

能夠重複進行直到該數字再也不可除。 您認爲這是個好方法嗎? 你有更好的主意嗎? ide

因爲對該主題的持續關注,我爲GitHub發佈了一種有效的解決方案 ,其中包含JavaScriptPHPPythonJava的實現 若是您願意,請添加您的解決方案:) ui


#1樓

您是否故意忽略了O,0和i? this

我剛剛基於Ryan的解決方案建立了一個PHP類。

<?php

    $shorty = new App_Shorty();

    echo 'ID: ' . 1000;
    echo '<br/> Short link: ' . $shorty->encode(1000);
    echo '<br/> Decoded Short Link: ' . $shorty->decode($shorty->encode(1000));


    /**
     * A nice shorting class based on Ryan Charmley's suggestion see the link on Stack Overflow below.
     * @author Svetoslav Marinov (Slavi) | http://WebWeb.ca
     * @see http://stackoverflow.com/questions/742013/how-to-code-a-url-shortener/10386945#10386945
     */
    class App_Shorty {
        /**
         * Explicitly omitted: i, o, 1, 0 because they are confusing. Also use only lowercase ... as
         * dictating this over the phone might be tough.
         * @var string
         */
        private $dictionary = "abcdfghjklmnpqrstvwxyz23456789";
        private $dictionary_array = array();

        public function __construct() {
            $this->dictionary_array = str_split($this->dictionary);
        }

        /**
         * Gets ID and converts it into a string.
         * @param int $id
         */
        public function encode($id) {
            $str_id = '';
            $base = count($this->dictionary_array);

            while ($id > 0) {
                $rem = $id % $base;
                $id = ($id - $rem) / $base;
                $str_id .= $this->dictionary_array[$rem];
            }

            return $str_id;
        }

        /**
         * Converts /abc into an integer ID
         * @param string
         * @return int $id
         */
        public function decode($str_id) {
            $id = 0;
            $id_ar = str_split($str_id);
            $base = count($this->dictionary_array);

            for ($i = count($id_ar); $i > 0; $i--) {
                $id += array_search($id_ar[$i - 1], $this->dictionary_array) * pow($base, $i - 1);
            }
            return $id;
        }
    }
?>

#2樓

public class UrlShortener {
    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static final int    BASE     = ALPHABET.length();

    public static String encode(int num) {
        StringBuilder sb = new StringBuilder();
        while ( num > 0 ) {
            sb.append( ALPHABET.charAt( num % BASE ) );
            num /= BASE;
        }
        return sb.reverse().toString();   
    }

    public static int decode(String str) {
        int num = 0;
        for ( int i = 0; i < str.length(); i++ )
            num = num * BASE + ALPHABET.indexOf(str.charAt(i));
        return num;
    }   
}

#3樓

C#版本:

public class UrlShortener 
{
    private static String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private static int    BASE     = 62;

    public static String encode(int num)
    {
        StringBuilder sb = new StringBuilder();

        while ( num > 0 )
        {
            sb.Append( ALPHABET[( num % BASE )] );
            num /= BASE;
        }

        StringBuilder builder = new StringBuilder();
        for (int i = sb.Length - 1; i >= 0; i--)
        {
            builder.Append(sb[i]);
        }
        return builder.ToString(); 
    }

    public static int decode(String str)
    {
        int num = 0;

        for ( int i = 0, len = str.Length; i < len; i++ )
        {
            num = num * BASE + ALPHABET.IndexOf( str[(i)] ); 
        }

        return num;
    }   
}

#4樓

alphabet = map(chr, range(97,123)+range(65,91)) + map(str,range(0,10))

def lookup(k, a=alphabet):
    if type(k) == int:
        return a[k]
    elif type(k) == str:
        return a.index(k)


def encode(i, a=alphabet):
    '''Takes an integer and returns it in the given base with mappings for upper/lower case letters and numbers 0-9.'''
    try:
        i = int(i)
    except Exception:
        raise TypeError("Input must be an integer.")

    def incode(i=i, p=1, a=a):
        # Here to protect p.                                                                                                                                                                                                                
        if i <= 61:
            return lookup(i)

        else:
            pval = pow(62,p)
            nval = i/pval
            remainder = i % pval
            if nval <= 61:
                return lookup(nval) + incode(i % pval)
            else:
                return incode(i, p+1)

    return incode()



def decode(s, a=alphabet):
    '''Takes a base 62 string in our alphabet and returns it in base10.'''
    try:
        s = str(s)
    except Exception:
        raise TypeError("Input must be a string.")

    return sum([lookup(i) * pow(62,p) for p,i in enumerate(list(reversed(s)))])a

這是我須要的版本。


#5樓

我有一個問題的變體,由於我存儲了許多不一樣做者的網頁,而且須要防止經過猜想發現網頁。 所以,個人短網址在頁碼的Base-62字符串中添加了幾個額外的數字。 這些額外的數字是從頁面記錄自己的信息中生成的,它們確保3844個URL中只有1個有效(假定2個數字爲Base-62)。 您能夠在http://mgscan.com/MBWL上看到概述說明。

相關文章
相關標籤/搜索