Подтвердить что ты не робот

Как реализовать короткий URL-адрес, например URL-адреса в твиттере?

Если есть длинный URL-адрес, я хочу создать короткий URL-адрес, например, в twitter, есть ли способ реализовать в ruby?

Спасибо заранее.

4b9b3361

Ответ 1

Самый простой способ:

  • сохранить базу данных всех URL-адресов
  • когда вы вставляете новый URL-адрес в базу данных, узнайте идентификатор первичного ключа с автоматическим инкрементным целым.
  • закодировать это целое число на основание 36 или 62 (цифры + строчные буквы альфа или цифры + смешанный регистр). Вуаля! У вас короткий URL-адрес!

Кодирование на основание 36/декодирование с базы 36 в Ruby прост:

12341235.to_s(36)
#=> "7cik3"

"7cik3".to_i(36)
#=> 12341235

Кодировка на базу 62 немного сложнее. Вот один из способов сделать это:

module AnyBase
  ENCODER = Hash.new do |h,k|
    h[k] = Hash[ k.chars.map.with_index.to_a.map(&:reverse) ]
  end
  DECODER = Hash.new do |h,k|
    h[k] = Hash[ k.chars.map.with_index.to_a ]
  end
  def self.encode( value, keys )
    ring = ENCODER[keys]
    base = keys.length
    result = []
    until value == 0
      result << ring[ value % base ]
      value /= base
    end
    result.reverse.join
  end
  def self.decode( string, keys )
    ring = DECODER[keys]
    base = keys.length
    string.reverse.chars.with_index.inject(0) do |sum,(char,i)|
      sum + ring[char] * base**i
    end
  end
end

... и здесь он находится в действии:

base36 = "0123456789abcdefghijklmnopqrstuvwxyz"
db_id = 12341235
p AnyBase.encode( db_id, base36 )
#=> "7cik3"
p AnyBase.decode( "7cik3", base36 )
#=> 12341235

base62 = [ *0..9, *'a'..'z', *'A'..'Z' ].join
p AnyBase.encode( db_id, base62 )
#=> "PMwb"
p AnyBase.decode( "PMwb", base62 )
#=> 12341235

Edit

Если вы хотите избежать URL-адресов, которые являются английскими словами (например, четырехсловными ругательствами), вы можете использовать набор символов, которые не включают гласные:

base31 = ([*0..9,*'a'..'z'] - %w[a e i o u]).join
base52 = ([*0..9,*'a'..'z',*'A'..'Z'] - %w[a e i o u A E I O U]).join

Однако при этом у вас все еще есть проблемы вроде AnyBase.encode(328059,base31) или AnyBase.encode(345055,base31) или AnyBase.encode(450324,base31). Таким образом, вы можете также избегать чисел, похожих на гласные:

base28 = ([*'0'..'9',*'a'..'z'] - %w[a e i o u 0 1 3]).join
base49 = ([*'0'..'9',*'a'..'z',*'A'..'Z'] - %w[a e i o u A E I O U 0 1 3]).join

Это также позволит избежать проблемы "Является ли это 0 или O?"? и "Это 1 или я?".

Ответ 2

Я использую bitly gem. Это очень просто.

gem install bitly

# Use api version 3 or get a deprecation warning
Bitly.use_api_version_3

# Create a client
bitly = Bitly.new(username, api_key)

# Call method shorten
bitly.shorten('http://www.google.com').short_url

Ответ 3

Хорошо, вы могли бы генерировать короткие URL-адреса, используя API-интерфейсы для множества сокращающих URL-адресов. Почти все сервисы, которые там предоставляются, предоставляют API для того, чтобы вы могли ссылаться и сокращать URL-адрес, именно так работают клиенты Twitter. Для получения дополнительной информации посетите веб-сайт, посвященный сокращению URL-адресов.

Если вы хотите создать такую ​​услугу самостоятельно, это также может быть довольно простым, все, что вам нужно сделать, это по существу поддерживать внутреннее сопоставление (в базе данных) между исходным длинным URL-адресом и специальным коротким URL-адресом (сгенерированным тобой). И когда вы получаете запрос на определенный короткий URL-адрес, вы должны иметь возможность получить исходный длинный URL-адрес из базы данных и перенаправить пользователя к тому же.

Ответ 4

Для Ruby 2.0 замените метод декодирования на:

def self.decode( string, keys )
  ring = DECODER[keys]
  base = keys.length
  string.reverse.chars.map.with_index.inject(0) do |sum,(char,i)|
    sum + ring[char] * base**i
  end
end