如何使用Python制作独特的短URL?

时间:2009-09-30 11:16:11

标签: python url uuid tinyurl short-url

如何在Python http://imgur.com/gM19ghttp://tumblr.com/xzh3bi25y中创建Python中的唯一网址 当从python使用uuid时,我得到一个非常大的。我想要一些更短的URL。

12 个答案:

答案 0 :(得分:23)

编辑:在这里,我为您编写了一个模块。用它。 http://code.activestate.com/recipes/576918/


从1开始计数将保证简短,唯一的URL。 / 1,/ 2,/ 3 ......等等。

在字母表中添加大写和小写字母会产生类似问题的网址。而你只是计算基数为62而不是基数为10。

现在唯一的问题是网址是连续出现的。要解决这个问题,请在此处阅读我对此问题的回答:

Map incrementing integer range to six-digit base 26 max, but unpredictably

基本上,方法是简单地在递增值中交换位,以便在保持确定性的同时给出随机性的外观,并保证您没有任何碰撞。

答案 1 :(得分:16)

我不确定大多数网址缩短程序是否使用随机字符串。我的印象是他们将URL写入数据库,然后使用新记录的整数ID作为短URL,编码基数为36或62(字母+数字)。

将int转换为任意基础的字符串的Python代码是here

答案 2 :(得分:5)

此模块将执行您想要的操作,保证字符串是全局唯一的(它是UUID):

http://pypi.python.org/pypi/shortuuid/0.1

如果你需要更短的东西,你应该能够将它截断到所需的长度,并且仍能获得可以合理避免冲突的东西。

答案 3 :(得分:3)

Python short_url非常棒。

以下是一个例子:

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)

那就是:)

希望这会有所帮助。

答案 4 :(得分:3)

这个答案来得很晚但是当我打算创建一个URL缩短项目时,我偶然发现了这个问题。现在我已经实现了一个功能齐全的URL缩短项目(源代码在{3}}它在Python 3中)我正在添加一个答案,说明它是如何完成的。这样它可以帮助别人:

任何URL缩短程序背后的基本原则是从长URL获取一个int,然后使用base62(base32等)编码将此int转换为更易读的短URL。

这个int是如何生成的? 大多数URL缩短程序使用一些自动递增数据存储区将URL添加到数据存储区并使用autoincrement id来获取int的base62编码。

示例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如何解码。查看amitt001/pygmy

处的完整base62编码/解码代码

此答案中的所有链接都缩短了我创建的项目

答案 5 :(得分:2)

UUID很长的原因是因为它们包含大量信息,因此可以保证它们在全球范围内是唯一的。

如果你想要更短的东西,那么你需要做一些事情,比如生成一个随机字符串,检查它是否在已经生成的字符串的Universe中,并重复直到你得到一个未使用的字符串。你还需要注意这里的并发性(如果在插入字符串集之前由一个单独的进程生成相同的字符串会怎么样?)。

如果你需要一些帮助在Python中生成随机字符串,这other question可能会有所帮助。

答案 6 :(得分:2)

Hashids是一个非常棒的工具。

编辑:

以下是如何使用Hashids使用Python生成唯一的短URL:

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)

答案 7 :(得分:1)

这不是真正重要的,这是Python,但你只需要一个映射到你想要的长度的哈希函数。例如,可能使用MD5,然后只使用第一个n个字符。在这种情况下,你必须注意碰撞,所以你可能想要在碰撞检测方面选择一些更强大的东西(比如使用素数来循环遍历散列字符串的空间)。

答案 8 :(得分:1)

我不知道你是否可以使用它,但我们在Zope中生成基于当前时间字符串获得唯一数字id的内容对象,以毫秒为单位(例如,1254298969501)

也许你可以猜到其余的。使用此处描述的配方: How to convert an integer to the shortest url-safe string in Python?,我们即时编码和解码真实ID,无需存储。例如,在基数62中,13位整数减少到7个字母数字字符。

为了完成实施,我们注册了一个简短的(xxx.yy)域名,该域名解码并对“未找到”的网址进行301重定向,

如果我重新开始,我会在编码之前从数字id中减去“重新开始”时间(以毫秒为单位),然后在解码时重新添加它。否则在生成对象时。随你。那会更短..

答案 9 :(得分:0)

试试这个http://code.google.com/p/tiny4py/ ......它仍在开发中,但非常有用!!

答案 10 :(得分:0)

我的目标:生成指定固定长度的唯一标识符,其中包含字符0-9a-z。例如:

zcgst5od
9x2zgn0l
qa44sp0z
61vv1nl5
umpprkbt
ylg4lmcy
dec0lu1t
38mhd8i5
rx00yf0e
kc2qdc07

这是我的解决方案。 this answer改编自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://stackoverflow.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()

答案 11 :(得分:0)

您可以生成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))
  

N = 10的输出:

     

'G1ZRbouk2U'