2009-09-30 169 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编码的码在这个答案的所有链接都来自我创建

项目缩短