¿Cómo hacer una URL corta única con Python?
uuid tinyurl (11)
¿Cómo puedo crear una URL única en Python a la http://imgur.com/gM19g o http://tumblr.com/xzh3bi25y Cuando uso uuid de python obtengo una muy grande? Quiero algo más corto para las URL.
Este módulo hará lo que usted quiera, garantizando que la cadena sea globalmente única (es un UUID):
http://pypi.python.org/pypi/shortuuid/0.1
Si necesita algo más corto, debería poder truncarlo a la longitud deseada y obtener algo que probablemente evite los enfrentamientos.
La razón por la que los UUID son largos es porque contienen mucha información, de modo que se puede garantizar que son únicos en el mundo.
Si quieres algo más corto, entonces necesitarás hacer algo como generar una cadena aleatoria, verificar si está en el universo de cadenas ya generadas, y repetir hasta que obtengas una cadena sin usar. También tendrá que tener cuidado con la concurrencia aquí (¿qué pasa si la misma cadena se genera mediante un proceso separado antes de insertarla en el conjunto de cadenas?).
Si necesita ayuda para generar cadenas aleatorias en Python, esta otra pregunta podría ser útil.
No estoy seguro de que la mayoría de los acortadores de URL usen una cadena aleatoria. Mi impresión es que escriben la URL en una base de datos, luego usan la ID entera del nuevo registro como la URL corta, la base codificada 36 o 62 (letras + dígitos).
El código de Python para convertir un int a una cadena en bases arbitrarias está here .
No sé si puede usar esto, pero generamos objetos de contenido en Zope que obtienen identificadores numéricos únicos basados en cadenas de tiempo actuales, en milisegundos (por ejemplo, 1254298969501)
Quizás puedas adivinar el resto. Usando la receta que se describe aquí: ¿Cómo convertir un entero a la cadena más corta segura para url en Python? , codificamos y decodificamos la identificación real sobre la marcha, sin necesidad de almacenamiento. Un número entero de 13 dígitos se reduce a 7 caracteres alfanuméricos en la base 62, por ejemplo.
Para completar la implementación, registramos un nombre de dominio corto (xxx.yy), que decodifica y hace un redireccionamiento 301 para las URL "no encontradas",
Si comenzara de nuevo, restaría el tiempo de "inicio" (en milisegundos) del ID numérico antes de la codificación, luego lo volvería a agregar al decodificar. O bien al generar los objetos. Lo que sea. Eso sería mucho más corto ...
Prueba esto http://code.google.com/p/tiny4py/ ... ¡Todavía está en desarrollo, pero es muy útil!
Python''s short_url es increíble.
Aquí hay un ejemplo:
import short_url
id = 20 # your object id
domain = ''mytiny.domain''
shortened_url = "http://{}/{}".format(
domain,
short_url.encode_url(id)
)
Y para decodificar el código:
decoded_id = short_url.decode_url(param)
Eso es :)
Espero que esto ayude
Realmente no importa que esto sea Python, pero solo necesitas una función hash que se corresponda con la longitud que desees. Por ejemplo, tal vez use MD5 y luego solo tome los primeros n
caracteres. Sin embargo, tendrá que tener cuidado con las colisiones en ese caso, por lo que puede elegir algo un poco más robusto en términos de detección de colisiones (como usar primos para recorrer el espacio de las cadenas de hash).
Sé que esta respuesta llega bastante tarde, pero me encontré con esta pregunta cuando estaba planeando crear un proyecto de acortador de URL. Ahora que he implementado un proyecto de acortador de URL completamente funcional (código fuente en amitt001/pygmy está en Python 3), estoy agregando una respuesta sobre cómo se hace. Para que pueda ayudar a alguien más:
El principio básico detrás de cualquier acortador de URL es obtener una int de una URL larga y luego usar la codificación base62 (base32, etc.) para convertir esta int a una URL corta más legible.
¿Cómo se genera este int? La mayoría del acortador de URL utiliza algún almacén de datos de incremento automático para agregar URL al almacén de datos y usar el identificador de autoincrement para obtener la codificación base62 de int.
La muestra base62 que codifica desde el programa de cadenas:
# 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
Este es solo un código parcial y no muestra cómo se decodifica base62. Consulte el código de codificación base62 completo en core/hashdigest.py
Todo el enlace en esta respuesta se abrevia del proyecto que creé
Hashids es una herramienta increíble para esto.
Editar:
Aquí se explica cómo usar Hashids para generar una URL corta única con 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)
Editar : Aquí, escribí un módulo para ti. Úselo. http://code.activestate.com/recipes/576918/
Contar desde 1 garantizará URLS cortos y únicos. / 1, / 2, / 3 ... etc.
Agregar letras mayúsculas y minúsculas a su alfabeto dará URLs como las de su pregunta. Y solo estás contando en base-62 en lugar de base-10.
Ahora el único problema es que las URL vienen consecutivamente. Para arreglar eso, lea mi respuesta a esta pregunta aquí:
Asignar un mapa de rango entero a la base de seis dígitos 26 máx., Pero impredeciblemente
Básicamente, el enfoque es simplemente intercambiar bits en el valor de incremento para dar la apariencia de aleatoriedad mientras se mantiene el determinismo y se garantiza que no haya colisiones.
Mi objetivo: generar un identificador único de una longitud fija especificada que consta de los caracteres 0-9
y az
. Por ejemplo:
zcgst5od
9x2zgn0l
qa44sp0z
61vv1nl5
umpprkbt
ylg4lmcy
dec0lu1t
38mhd8i5
rx00yf0e
kc2qdc07
Aquí está mi solución. (Adaptado de esta respuesta por 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://.com/a/561809/1497596
# Author: https://.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()