Преобразовать шестизначную строку UUID с 32 символами в короткий идентификатор "YouTube" и обратно
Я назначаю все мои документы MongoDB GUID с помощью uuid.uuid1(). Я хочу, чтобы я мог получить 11-значный, уникальный, чувствительный к регистру идентификатор YouTube, такой как
1_XmY09uRJ4
из полученной шестнадцатеричной строки uuid, которая выглядит как
ae0a0c98-f1e5-11e1-9t2b-1231381dac60
Я хочу иметь возможность сопоставить сокращенный идентификатор с шестнадцатеричным и наоборот, динамически, без необходимости хранить другую строку в базе данных. Кто-нибудь имеет какой-то пример кода или может указать мне в сторону модуля или формулы, которые могут это сделать?
Ответы
Ответ 1
Преобразуйте нижележащие байты в значение base64, удаляя отступы =
и новую строку.
Возможно, вы захотите использовать base64.urlsafe_b64encode()
чтобы избежать использования /
и +
(вместо них используются _
и -
), поэтому результирующая строка может использоваться как элемент пути 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-значные идентификаторы, вероятно, хранятся в базе данных для удобства поиска и основаны на меньшем значении.
Ответ 2
Вы можете посмотреть в модель Python base64
. GUID, по сути, представляет собой представление числа 16, и вы можете обрезать дефисы, декодировать из базы 16 и закодировать в базу 64. Для возврата в обратном направлении требуется декодирование с базы 64, кодирование в базе 16 и вставка дефис в соответствующих местах.
Ответ 3
Для тех, кто ищет способ сокращения uuids безопасным способом URL, действительно полезный ответ от @MartijnPieters можно упростить, если использовать модуль base64
для обработки символов, которые не являются безопасными по URL, аналогично комментарию к этому ответу от @okoboko. (без нескольких ненужных битов).
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}==')))