如何用 Python 制作唯一的短 URL?

Posted

技术标签:

【中文标题】如何用 Python 制作唯一的短 URL?【英文标题】:How to make unique short URL with Python? 【发布时间】:2010-12-02 14:54:38 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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


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

在您的字母表中添加大写和小写字母会给出与您问题中的 URL 类似的 URL。而且你只是在以 62 为基数而不是以 10 为基数。

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

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

基本上,该方法是简单地交换递增值中的位,以呈现随机性,同时保持确定性并保证您没有任何冲突。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案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】:

这个模块会做你想做的事,保证字符串是全局唯一的(它是一个 UUID):

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

如果您需要更短的内容,您应该能够将其截断到所需的长度,并且仍然可以获得可以合理避免冲突的内容。

【讨论】:

【参考方案5】:

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)

【讨论】:

【参考方案6】:

这个答案来得很晚,但是当我计划创建一个 URL 缩短器项目时,我偶然发现了这个问题。现在我已经实现了一个功能齐全的 URL 缩短器(amitt001/pygmy 的源代码)我在这里为其他人添加一个答案。

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

这个 int 是如何生成的?

大多数 URL 缩短器使用一些自动递增的数据存储来将 URL 添加到数据存储并使用自动递增的 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 编码的部分代码。在core/hashdigest.py查看完整的base62编码/解码代码

这个答案中的所有链接都是从我创建的项目中缩短的

【讨论】:

【参考方案7】:

UUID 之所以长是因为它们包含大量信息,因此可以保证它们是全局唯一的。

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

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

【讨论】:

【参考方案8】:

这是 Python 并不重要,但您只需要一个映射到您想要的长度的哈希函数。例如,可能使用 MD5,然后只取第一个 n 字符。不过,在这种情况下,您必须注意碰撞,因此您可能希望在碰撞检测方面选择更强大的东西(例如使用素数在哈希字符串空间中循环)。

【讨论】:

【参考方案9】:

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

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

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

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

【讨论】:

【参考方案10】:

可以生成N个随机字符串:

import string
import random

def short_random_string(N:int) -> str:

    return ''.join(random.SystemRandom().choice(
        string.ascii_letters + \
        string.digits) for _ in range(N)
    )

所以,

print (short_random_string(10) )
#'G1ZRbouk2U'

全部小写

print (short_random_string(10).lower() )
#'pljh6kp328'

【讨论】:

【参考方案11】:

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

【讨论】:

【参考方案12】:

我的目标:生成由字符0-9a-z 组成的指定固定长度的唯一标识符。例如:

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

这是我的解决方案。 (改编自this answerkmkaplan。)

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()

【讨论】:

以上是关于如何用 Python 制作唯一的短 URL?的主要内容,如果未能解决你的问题,请参考以下文章

拒绝降权!教你用 Python 确保制作的短视频独一无二

如何用python制作条形码

如何用 Python 制作 GIF 动图

如何用python3制作unicode字符串

如何用Python制作3D动态航线图

如何用Python语言制作打字游戏?快教教我,急急急