Как реализовать короткий URL-адрес, как URL-адреса в Twitter? - PullRequest
25 голосов
/ 14 июня 2011

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

Заранее спасибо.

Ответы [ 4 ]

61 голосов
/ 14 июня 2011

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

  1. хранить базу данных всех URL
  2. , когда вы вставляете новый URL в базу данных, узнаете идентификатор автоматически увеличивающегося целого числапервичный ключ.
  3. кодирует это целое число в основание 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

Редактировать

Если выЧтобы избежать использования 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 или I?».

12 голосов
/ 14 июня 2011

Я использую драгоценный камень bitly . Это действительно просто.

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
1 голос
/ 29 декабря 2013

Для 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
1 голос
/ 14 июня 2011

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

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

...