Я хочу создать службу сокращения URL-адресов, в которой вы можете записать длинный URL-адрес в поле ввода, а служба сокращает URL-адрес до " http://www.example.org/abcdef
".
Вместо " abcdef
" может быть любая другая строка, содержащая шесть символов a-z, A-Z and 0-9
. Это составляет 56 ~ 57 миллиардов возможных строк.
Мой подход:
У меня есть таблица базы данных с тремя столбцами:
- id, целое число, автоинкремент
- long, string, длинный URL, введенный пользователем
- короткий, строка, сокращенный URL (или только шесть символов)
Затем я вставил бы длинный URL в таблицу. Затем я бы выбрал значение автоинкремента для " id
" и построил его хеш. Этот хеш должен быть вставлен как " short
". Но какой хеш я должен создать? Алгоритмы хеширования, такие как MD5, создают слишком длинные строки. Я не использую эти алгоритмы, я думаю. Самостоятельный алгоритм тоже подойдет.
Моя идея:
Для " http://www.google.de/
" я получаю идентификатор автоинкремента 239472
. Затем я делаю следующие шаги:
short = '';
if divisible by 2, add "a"+the result to short
if divisible by 3, add "b"+the result to short
... until I have divisors for a-z and A-Z.
Это может повторяться до тех пор, пока число больше не будет делиться. Как вы думаете, это хороший подход? У тебя есть идея получше?
Из-за постоянного интереса к этой теме я опубликовал эффективное решение для GitHub с реализациями для JavaScript , PHP , Python и Java . Добавьте ваши решения, если хотите :)
encode()
иdecode()
функции. Поэтому необходимо выполнить следующие шаги: (1) сохранить URL-адрес в базе данных (2) получить уникальный идентификатор строки для этого URL-адреса из базы данных (3) преобразовать целочисленный идентификатор в короткую строкуencode()
, например,273984
вf5a4
(4) использовать короткую строку (напримерf4a4
) в URL для общего доступа (5) При получении запроса на короткую строку (например20a8
), декодируйте строку в целочисленный идентификатор с помощьюdecode()
(6). Найдите URL в базе данных для данного идентификатора. Для конвертации используйте: github.com/delight-im/ShortURLОтветы:
Я бы продолжил ваш подход "конвертировать число в строку". Однако вы поймете, что предложенный вами алгоритм не работает, если ваш идентификатор простое и больше 52 .
Теоретические основы
Вам нужна биективная функция f . Это необходимо, чтобы вы могли найти обратную функцию g ('abc') = 123 для вашей функции f (123) = 'abc' . Это означает:
Как преобразовать идентификатор в сокращенный URL
[a-zA-Z0-9]
. Он содержит 62 буквы .Возьмите автоматически сгенерированный уникальный числовой ключ (
id
например, автоинкремент таблицы MySQL).Для этого примера я буду использовать 125 10 (125 с основанием 10).
Теперь вам нужно конвертировать 125 10 в X 62 (база 62).
125 10 = 2 × 62 1 + 1 × 62 0 =
[2,1]
Это требует использования целочисленного деления и по модулю. Пример псевдокода:
Теперь сопоставьте индексы 2 и 1 с вашим алфавитом. Вот как может выглядеть ваше отображение (например, с массивом):
При 2 → c и 1 → b вы получите cb 62 в качестве сокращенного URL.
Как разрешить сокращенный URL к начальному идентификатору
Обратное еще проще. Вы просто делаете обратный поиск в вашем алфавите.
e9a 62 будет преобразован в «4-ю, 61-ю и 0-ю букву в алфавите».
e9a 62 =
[4,61,0]
= 4 × 62 2 + 61 × 62 1 + 0 × 62 0 = 19158 10Теперь найдите вашу базу данных с помощью
WHERE id = 19158
и выполните перенаправление.Пример реализации (предоставляется комментаторами)
источник
3792586=='F_ck'
с u вместо _). Я бы исключил некоторые символы, такие как U / U, чтобы минимизировать это.Почему вы хотите использовать хеш?
Вы можете просто использовать простой перевод значения автоинкремента в буквенно-цифровое значение. Вы можете сделать это легко с помощью некоторого базового преобразования. Допустим, у вас есть пространство символов (AZ, az, 0-9 и т. Д.), Состоящее из 40 символов, преобразуйте идентификатор в число с основанием 40 и используйте символы в качестве цифр.
источник
источник
Не ответ на ваш вопрос, но я бы не стал использовать сокращенные URL-адреса с учетом регистра. Их трудно запомнить, как правило, нечитаемые (многие шрифты отображают 1 и l, 0 и O и другие символы очень похожи, так что почти невозможно различить их) и подвержены прямым ошибкам. Попробуйте использовать только нижний или верхний регистр.
Кроме того, попробуйте создать формат, в котором вы будете смешивать цифры и символы в заранее определенной форме. Существуют исследования, которые показывают, что люди, как правило, запоминают одну форму лучше, чем другие (например, номера телефонов, где номера сгруппированы в определенной форме). Попробуйте что-то вроде num-char-char-num-char-char. Я знаю, что это понизит комбинации, особенно если у вас нет прописных и строчных букв, но это будет более полезным и, следовательно, полезным.
источник
Мой подход: взять идентификатор базы данных, затем Base36 кодировать его . Я НЕ буду использовать как заглавные, так и строчные буквы, потому что это делает передачу этих URL-адресов по телефону кошмаром, но вы, конечно, можете легко расширить эту функцию до базового 62 en / декодера.
источник
Вот мой класс PHP 5.
источник
Решение Node.js и MongoDB
Так как мы знаем формат, который MongoDB использует для создания нового ObjectId с 12 байтами.
Пример (я выбираю случайную последовательность) a1b2c3d4e5f6g7h8i9j1k2l3
Поскольку счетчик будет уникальным, если мы храним данные на одной машине, мы можем получить их, не сомневаясь, что они будут повторяться.
Таким образом, короткий URL будет счетчиком, а вот фрагмент кода, предполагающий, что ваш сервер работает правильно.
источник
Версия C #:
источник
Вы можете хэшировать весь URL, но если вы просто хотите сократить идентификатор, сделайте, как предложил Марсель. Я написал эту реализацию Python:
https://gist.github.com/778542
источник
Я продолжаю увеличивать целочисленную последовательность для каждого домена в базе данных и использую Hashids для кодирования целого числа в URL-пути.
Я запустил скрипт, чтобы увидеть, сколько времени потребуется, чтобы исчерпать длину символа. Для шести символов он может делать
164,916,224
ссылки, а затем доходит до семи символов. Битли использует семь символов. Под пятью персонажами выглядит странно для меня.Хашиды могут декодировать URL-путь обратно к целому числу, но более простым решением является использование всей короткой ссылки
sho.rt/ka8ds3
в качестве первичного ключа.Вот полная концепция:
источник
Если вы не хотите заново изобретать колесо ... http://lilurl.sourceforge.net/
источник
источник
Вот моя версия для тех, кому это нужно.
источник
Взгляните на https://hashids.org/ это с открытым исходным кодом и на многих языках.
На их странице изложены некоторые подводные камни других подходов.
источник
Почему бы просто не перевести свой идентификатор в строку? Вам просто нужна функция, которая отображает цифру, скажем, от 0 до 61, в одну букву (верхний / нижний регистр) или цифру. Затем примените это для создания, скажем, четырехбуквенных кодов, и вы получите 14,7 миллионов URL-адресов.
источник
Вот достойная функция кодирования URL для PHP ...
источник
Не знаю, сочтет ли кто-нибудь это полезным - это скорее метод 'hack n slash', но он прост и хорошо работает, если вам нужны только определенные символы.
источник
Вы пропустили O, 0 и я специально?
Я только что создал класс PHP на основе решения Райана.
источник
Это то, что я использую:
Это очень быстро и может занимать длинные целые числа.
источник
Для аналогичного проекта, чтобы получить новый ключ, я делаю функцию-обертку вокруг генератора случайных строк, который вызывает генератор, пока не получу строку, которая еще не использовалась в моей хеш-таблице. Этот метод замедлится, как только ваше пространство имен начнет заполняться, но, как вы сказали, даже с 6 символами у вас будет достаточно пространства для работы.
источник
У меня есть вариант проблемы в том, что я храню веб-страницы от разных авторов, и мне нужно предотвратить обнаружение страниц путем догадок. Поэтому мои короткие URL-адреса добавляют пару дополнительных цифр к строке Base-62 для номера страницы. Эти дополнительные цифры генерируются из информации в самой записи страницы, и они гарантируют, что только 1 из 3844 URL-адресов являются действительными (при условии 2-значный Base-62). Вы можете увидеть общее описание на http://mgscan.com/MBWL .
источник
Очень хороший ответ, я создал реализацию bjf на Golang:
Размещено на github: https://github.com/xor-gate/go-bjf
источник
источник
Реализация в Scala:
Тестовый пример с тестом Scala:
источник
Функция основана на классе Xeoncross
источник
Вот реализация Node.js, которая, вероятно, будет bit.ly. создать очень случайную строку из семи символов.
Он использует криптографию Node.js для генерации очень случайного набора из 25 символов вместо случайного выбора семи символов.
источник
Моя версия Python 3
источник
Качественное решение Node.js / JavaScript см. В модуле id-shorttener , который тщательно протестирован и уже несколько месяцев используется в производстве.
Он обеспечивает эффективное сокращение идентификатора / URL-адреса при поддержке подключаемого хранилища по умолчанию Redis , и вы даже можете настроить свой короткий набор символов идентификатора и определить, является ли сокращение идемпотентным . Это важное различие, которое учитывают не все средства сокращения URL.
В отношении других ответов здесь, этот модуль реализует превосходный принятый ответ Марселя Джекверта выше.
Основу решения предоставляет следующий фрагмент Redis Lua :
источник
Почему бы просто не сгенерировать случайную строку и не добавить ее к базовому URL? Это очень упрощенная версия этого в C # .
Затем просто добавьте случайную строку в baseURL:
Помните, что это очень упрощенная версия, и, возможно, метод RandomString может создавать повторяющиеся строки. В процессе производства вы бы хотели учесть наличие дублирующихся строк, чтобы у вас всегда был уникальный URL-адрес. У меня есть некоторый код, который учитывает дублирующиеся строки, запрашивая таблицу базы данных, которой я мог бы поделиться, если кому-то интересно.
источник
Это мои первоначальные мысли, и можно больше думать, или провести какое-то моделирование, чтобы увидеть, работает ли оно хорошо или требуется какое-либо улучшение:
Мой ответ - запомнить длинный URL-адрес в базе данных и использовать идентификатор
0
для9999999999999999
(или сколь угодно большого числа).Но ID 0
9999999999999999
может быть проблемой, потому чтоA
-Z
a
-z
0
-9
_
и-
)0
до9999999999999999
равномерно, то хакеры могут посетить их в таком порядке , и знать , что URL - адреса люди посылают друг другу, так что это может быть вопрос о конфиденциальностиМы можем сделать это:
0
для999
одного сервера, сервера A, поэтому теперь сервер A имеет 1000 таких идентификаторов. Таким образом, если существует 20 или 200 серверов, постоянно нуждающихся в новых идентификаторах, не нужно постоянно запрашивать каждый новый идентификатор, а вместо этого запрашивать один раз 1000 идентификаторов.000...00000001
получается10000...000
, что при преобразовании в base64 он будет неравномерно увеличивать ID каждый раз.0xD5AA96...2373
(как секретный ключ), и некоторые биты будут перевернуты. (всякий раз, когда секретный ключ имеет 1 бит, он переворачивает бит идентификатора). Это сделает идентификаторы еще сложнее угадать и выглядеть более случайнымВ соответствии с этой схемой один сервер, который выделяет идентификаторы, может формировать идентификаторы, как и 20 или 200 серверов, запрашивающих назначение идентификаторов. Распределяющий сервер должен использовать блокировку / семафор, чтобы два запрашивающих сервера не могли получить один и тот же пакет (или если он принимает одно соединение за раз, это уже решает проблему). Поэтому мы не хотим, чтобы строка (очередь) была слишком длинной для ожидания выделения. Вот почему выделение 1000 или 10000 за раз может решить проблему.
источник