Как сделать уникальный короткий URL с помощью Python?
Как сделать уникальный URL-адрес в Python а-ля https://imgur.com/gM19g или http://tumblr.com/xzh3bi25y При использовании uuid из Python я получаю очень большой. Я хочу что-то более короткое для URL.
11 ответов
Редактировать: Здесь я написал модуль для вас. Используй это. http://code.activestate.com/recipes/576918/
Подсчет от 1 гарантирует короткие уникальные URL. /1, /2, /3 ... и т. Д.
Добавление заглавных и строчных букв в ваш алфавит даст URL-адреса, подобные тем, которые указаны в вашем вопросе. И ты просто считаешь в базе 62 вместо базы 10.
Теперь единственная проблема заключается в том, что URL приходят последовательно. Чтобы это исправить, прочитайте мой ответ на этот вопрос здесь:
Увеличение целочисленного диапазона карты до шестизначного 26 макс., Но непредсказуемо
В основном, подход заключается в том, чтобы просто поменять местами инкрементное значение, чтобы создать впечатление случайности, сохраняя при этом детерминизм и гарантируя отсутствие коллизий.
Я не уверен, что большинство сокращателей URL используют случайную строку. У меня сложилось впечатление, что они записывают URL-адрес в базу данных, а затем используют целочисленный идентификатор новой записи в качестве короткого URL-адреса, закодированный в виде базы 36 или 62 (буквы + цифры).
Python код для преобразования int в строку в произвольных базах здесь.
Вот пример:
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)
Это оно:)
Надеюсь, это поможет.
Хашидс - отличный инструмент для этого.
Редактировать:
Вот как использовать Hashids для создания уникального короткого URL с помощью 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)
Я знаю, что этот ответ приходит довольно поздно, но я наткнулся на этот вопрос, когда планировал создать проект сокращения URL. Теперь, когда я реализовал полностью функциональный проект сокращения URL-адресов (исходный код на amitt001 / pygmy, он на Python 3), я добавляю ответ, как это делается. Так что это может помочь кому-то еще:
Основной принцип, используемый для сокращения URL-адресов, состоит в том, чтобы получить int из длинного URL-адреса, а затем использовать кодировку base62 (base32 и т. Д.) Для преобразования этого int в более читаемый короткий URL-адрес.
Как генерируется этот int? Большинство средств сокращения URL-адресов используют некоторое автоинкрементное хранилище данных для добавления URL-адреса в хранилище данных и используют идентификатор автоинкремента для получения кодировки base62 для int.
Пример кодировки 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. Ознакомьтесь с полным кодом кодировки base62 в core / hashdigest.py
Все ссылки в этом ответе сокращены из проекта, который я создал
Этот модуль будет делать то, что вы хотите, гарантируя, что строка глобально уникальна (это UUID):
http://pypi.python.org/pypi/shortuuid/0.1
Если вам нужно что-то более короткое, вы сможете укоротить его до желаемой длины и при этом получить что-то, что, вероятно, позволит избежать столкновений.
Причина, по которой UUID являются длинными, заключается в том, что они содержат много информации, так что они могут быть гарантированно глобально уникальными.
Если вы хотите что-то более короткое, то вам нужно сделать что-то вроде генерации случайной строки, проверить, находится ли она во вселенной уже сгенерированных строк, и повторять до тех пор, пока не получите неиспользованную строку. Вам также необходимо следить за параллелизмом (что, если эта же строка будет сгенерирована отдельным процессом до того, как вы вставите ее в набор строк?).
Если вам нужна помощь в генерации случайных строк в Python, этот другой вопрос может помочь.
На самом деле не имеет значения, что это Python, но вам просто нужна хеш-функция, которая отображается на желаемую длину. Например, может быть, использовать MD5, а затем взять только первый n
персонажи. В этом случае вам придется следить за коллизиями, поэтому вы можете выбрать что-то более надежное с точки зрения обнаружения коллизий (например, использование простых чисел для циклического перемещения по пространству хеш-строк).
Вы можете сгенерировать случайную строку N:
import string
import random
def short_random_string(N:int) -> str:
return ''.join(random.SystemRandom().choice(
string.ascii_uppercase + \
string.ascii_lowercase + \
string.digits) for _ in range(N))
так,
print (short_random_string(10) )
#'G1ZRbouk2U'
все в нижнем регистре
print (short_random_string(10).lower() )
#'pljh6kp328'
Я не знаю, можете ли вы использовать это, но мы генерируем объекты содержимого в Zope, которые получают уникальные числовые идентификаторы, основанные на строках текущего времени, в миллисекундах (например, 1254298969501)
Может быть, вы можете угадать остальное. Используя рецепт, описанный здесь: Как преобразовать целое число в самую короткую URL-безопасную строку в Python?, мы кодируем и декодируем реальный идентификатор на лету, без необходимости хранения. Например, целое число из 13 цифр сокращено до 7 буквенно-цифровых символов в базе 62.
Чтобы завершить реализацию, мы зарегистрировали короткое (xxx.yy) имя домена, которое декодирует и выполняет перенаправление 301 для "не найденных" URL,
Если бы я начинал заново, я бы вычел время "в начале" (в миллис) из числового идентификатора до кодирования, а затем снова добавил бы его при декодировании. Или еще при создании объектов. Без разницы. Это было бы намного короче..
Попробуйте это http://code.google.com/p/tiny4py/... Это все еще в стадии разработки, но очень полезно!!
Моя цель: создать уникальный идентификатор указанной фиксированной длины, состоящий из символов 0-9
а также a-z
, Например:
zcgst5od
9x2zgn0l
qa44sp0z
61vv1nl5
umpprkbt
ylg4lmcy
dec0lu1t
38mhd8i5
rx00yf0e
kc2qdc07
Вот мое решение. (Адаптировано из этого ответа kmkaplan.)
import random
class IDGenerator(object):
ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz"
def __init__(self, length=8):
self._alphabet_length = len(self.ALPHABET)
self._id_length = length
def _encode_int(self, n):
# Adapted from:
# Source: https://stackru.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()