将UUID 32个字符的十六进制字符串转换为“YouTube风格”的短ID并返回

时间:2012-09-04 20:24:46

标签: python guid uuid

我正在使用uuid.uuid1()为我的所有MongoDB文档分配一个GUID。我想要一种方法,我可以得到一个11个字符,独特的,区分大小写的类似YouTube的ID,例如

1_XmY09uRJ4 

来自uuid的十六进制字符串,看起来像

ae0a0c98-f1e5-11e1-9t2b-1231381dac60

我希望能够将缩短的ID与十六进制匹配,反之亦然,而不必在数据库中存储另一个字符串。有没有人有一些示例代码或者可以指向可以执行此操作的模块或公式的方向?

3 个答案:

答案 0 :(得分:50)

将基础字节转换为base64值,剥离=填充和换行符。

您可能希望使用base64.urlsafe_b64encode() function来避免使用/+(而代之以_-),因此生成的字符串可以用作URL路径元素:

>>> import uuid, base64
>>> base64.urlsafe_b64encode(uuid.uuid1().bytes).rstrip(b'=').decode('ascii')
'81CMD_bOEeGbPwAjMtYnhg'

相反:

>>> uuid.UUID(bytes=base64.urlsafe_b64decode('81CMD_bOEeGbPwAjMtYnhg' + '=='))
UUID('f3508c0f-f6ce-11e1-9b3f-002332d62786')

将其转换为通用函数:

from base64 import urlsafe_b64decode, urlsafe_b64encode
from uuid import UUID

def uuid2slug(uuidstring):
    return urlsafe_b64encode(UUID(uuidstring).bytes).rstrip(b'=').decode('ascii')

def slug2uuid(slug):
    return str(uuid.UUID(bytes=urlsafe_b64decode(slug + '==')))

这为您提供了一种以更紧凑的形式表示16字节UUID的方法。进一步压缩并丢失信息,这意味着您无法再将其解压缩到完整的UUID。 16字节可以表示的全部值将永远不适合任何少于22个base64字符的值,每三个字节的输入需要4个字符,每个字符编码6位信息。

因此,YouTube的唯一字符串不是基于完整的16字节UUID,它们的11个字符ID可能存储在数据库中,以便于查找并基于较小的值。

答案 1 :(得分:1)

您可以查看Python的base64模型。 GUID本质上是一个数字的base-16表示,你可以修剪连字符,从base 16解码,然后编码到base 64.反过来需要从base 64解码,在base 16编码,并插入连字符在适当的地方。

答案 2 :(得分:0)

对于那些专门寻求以URL安全的方式缩短uuid的方法的人,可以使用@MartijnPieters模块来处理{url> {3}}中真正有用的答案,以简化一些不安全的字符类似于base64中对该答案的评论(没有一些不必要的内容)。

import base64
import uuid

# uuid to b64 string and back
uuid_to_b64str = base64.urlsafe_b64encode(uuid.uuid1().bytes).decode('utf8').rstrip('=\n')
b64str_to_uuid = uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuid_to_b64str}=='))

# uuid string to b64 string and back
uuidstr_to_b64str = base64.urlsafe_b64encode(uuid.UUID(str(uuid.uuid1())).bytes).decode('utf8').rstrip('=\n')
b64str_to_uuidstr = str(uuid.UUID(bytes=base64.urlsafe_b64decode(f'{uuidstr_to_b64str}==')))