Подтвердить что ты не робот

Преобразовать шестизначную строку UUID с 32 символами в короткий идентификатор "YouTube" и обратно

Я назначаю все мои документы MongoDB GUID с помощью uuid.uuid1(). Я хочу, чтобы я мог получить 11-значный, уникальный, чувствительный к регистру идентификатор YouTube, такой как

1_XmY09uRJ4 

из полученной шестнадцатеричной строки uuid, которая выглядит как

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

Я хочу иметь возможность сопоставить сокращенный идентификатор с шестнадцатеричным и наоборот, динамически, без необходимости хранить другую строку в базе данных. Кто-нибудь имеет какой-то пример кода или может указать мне в сторону модуля или формулы, которые могут это сделать?

4b9b3361

Ответ 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}==')))