2009-09-30 167 views

回答

2

原因的UUID是長是因爲它們含有大量的信息,以便他們可以保證是全球唯一的。

如果你想要的東西更短,那麼你需要做的是這樣生成一個隨機字符串,檢查它是否在已生成的字符串的宇宙,重複,直到你得到一個未使用的字符串。你還需要注意這裏的併發性(如果在插入到字符串集合之前,同一個字符串是由單獨的進程生成的,那該怎麼辦?)。

如果你需要一些幫助生成Python中隨機字符串,這other question可能的幫助。

1

這並不重要,這是Python,但你只需要一個哈希函數,映射到你想要的長度。例如,也許使用MD5,然後取第一個n個字符。儘管如此,在這種情況下,你必須小心碰撞,所以你可能想要在碰撞檢測方面選擇一些更強大的東西(比如使用素數來循環散列字符串空間)。

15

我不確定大多數URL縮短使用隨機字符串。我的印象是他們將URL寫入數據庫,然後使用新記錄的整數ID作爲短網址,編碼基數爲36或62(字母+數字)。

將int轉換爲任意基的字符串的Python代碼是here

22

編輯:在這裏,我寫了一個模塊,爲您服務。用它。 http://code.activestate.com/recipes/576918/


從1開始計數將保證短而唯一的URL。/1/2/3 ......等

添加大寫和小寫字母,以你的字母會給像那些在你的問題的URL。而你只需要計算base-62而不是base-10。

現在唯一的問題是URL是連續出現的。爲了解決這個問題,看我的這個問題的答案在這裏:

Map incrementing integer range to six-digit base 26 max, but unpredictably

基本上採取的辦法是簡單地換位左右的遞增值給隨機性的外觀,同時保持確定性和保證,你不有任何碰撞。

1

我不知道,如果你可以利用這一點,但我們產生的Zope內容對象基於當前時間的字符串,獲得獨特的數字ID,以毫秒(如1254298969501)

也許你能猜到休息。使用這裏描述的配方: How to convert an integer to the shortest url-safe string in Python?,我們實時編碼和解碼真實ID,無需存儲。例如,一個13位數的整數減少到基數爲62的7個字母數字字符。

爲了完成實現,我們註冊了一個short(xxx。yy)域名,解碼併爲「未找到」URL做301重定向,

如果我重新開始,我會從編碼前的數字ID中減去「開始」時間(以毫秒爲單位) ,然後在解碼時重新添加它。或者在生成對象時。隨你。這將是這樣短..

4

這個模塊會做你想做的,保證該字符串是全局唯一的(這是一個UUID):

http://pypi.python.org/pypi/shortuuid/0.1

如果你需要的東西更短,你應該能夠截斷它到所需的長度,並仍然有合理的可能避免衝突的東西。

0

我的目標:生成由字符0-9a-z的指定的固定長度的唯一標識符。例如:

zcgst5od 
9x2zgn0l 
qa44sp0z 
61vv1nl5 
umpprkbt 
ylg4lmcy 
dec0lu1t 
38mhd8i5 
rx00yf0e 
kc2qdc07 

這是我的解決方案。 (由kmkaplanthis answer改編。)

import random 

class IDGenerator(object): 
    ALPHABET = "abcdefghijklmnopqrstuvwxyz" 

    def __init__(self, length=8): 
     self._alphabet_length = len(self.ALPHABET) 
     self._id_length = length 

    def _encode_int(self, n): 
     # Adapted from: 
     # Source: https://stackoverflow.com/a/561809/1497596 
     # Author: https://stackoverflow.com/users/50902/kmkaplan 

     encoded = '' 
     while n > 0: 
      n, r = divmod(n, self._alphabet_length) 
      encoded = self.ALPHABET[r] + encoded 
     return encoded 

    def generate_id(self): 
     """Generate an ID without leading zeros. 

     For example, for an ID that is eight characters in length, the 
     returned values will range from '10000000' to 'zzzzzzzz'. 
     """ 

     start = self._alphabet_length**(self._id_length - 1) 
     end = self._alphabet_length**self._id_length - 1 
     return self._encode_int(random.randint(start, end)) 

if __name__ == "__main__": 
    # Sample usage: Generate ten IDs each eight characters in length. 
    idgen = IDGenerator(8) 

    for i in range(10): 
     print idgen.generate_id() 
1

Hashids是該一個真棒工具。

編輯:

下面介紹如何使用Hashids生成一個唯一的短網址與Python:

from hashids import Hashids 

pk = 123 # Your object's id 
domain = 'imgur.com' # Your domain 

hashids = Hashids(salt='this is my salt', min_length=6) 
link_id = hashids.encode(pk) 
url = 'http://{domain}/{link_id}'.format(domain=domain, link_id=link_id) 
1

Python的short_url是真棒。

下面是一個例子:

import short_url 

id = 20 # your object id 
domain = 'mytiny.domain' 

shortened_url = "http://{}/{}".format(
            domain, 
            short_url.encode_url(id) 
           ) 

而到了碼解碼:

decoded_id = short_url.decode_url(param) 

就是這樣:)

希望這會有所幫助。

0

我知道這個答案來得很晚,但當我打算創建一個URL shortener項目時,我偶然發現了這個問題。現在我已經實現了一個功能齊全的URL shortener項目(源代碼amitt001/pygmy它在Python 3中),我添加了一個如何完成的答案。以便它可以幫助其他人:

任何URL縮短器的基本原理是從long URL獲取int,然後使用base62(base32等)編碼將此int轉換爲更具可讀性的短URL。

int是如何產生的? 大多數URL shortener使用一些自動遞增數據存儲將URL添加到數據存儲,並使用autoincrement id來獲取int的base62編碼。從串程序

樣品base62編碼:

# Base-62 hash 

import string 
import time 

_BASE = 62 


class HashDigest: 
    """Base base 62 hash library.""" 

    def __init__(self): 
     self.base = string.ascii_letters + string.digits 
     self.short_str = '' 

    def encode(self, j): 
     """Returns the repeated div mod of the number. 
     :param j: int 
     :return: list 
     """ 
     if j == 0: 
      return [j] 
     r = [] 
     dividend = j 
     while dividend > 0: 
      dividend, remainder = divmod(dividend, _BASE) 
      r.append(remainder) 
     r = list(reversed(r)) 
     return r 

    def shorten(self, i): 
     """ 
     :param i: 
     :return: str 
     """ 
     self.short_str = "" 
     encoded_list = self.encode(i) 
     for val in encoded_list: 
      self.short_str += self.base[val] 
     return self.short_str 

這僅僅是一個局部碼和它不顯示base62如何解碼。看看在core/hashdigest.py

完整的base62編碼的碼在這個答案的所有鏈接都來自我創建

項目縮短