如何实现像 Twitter 中的 URL 一样的短 URL?

发布于 2024-11-15 04:49:43 字数 56 浏览 4 评论 0原文

如果有一个长网址,我想生成一个像 Twitter 中的短网址。有没有办法在 Ruby 中实现这个?

If there is a long url, I want to generate a short URL like those in Twitter. Is there some way to implement this in Ruby?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

司马昭之心 2024-11-22 04:49:43

最简单的方法是:

  1. 将所有URL存入数据库,
  2. 当你向数据库中插入一个新的URL时,找出自增整数主键的id。
  3. 将该整数编码为基数 36 或 62(数字 + 小写 alpha 或数字 + 混合大小写 alpha)。瞧!你有一个短网址!

在 Ruby 中,编码到基数 36/从基数 36 解码很简单:

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?”。

The easiest way is to:

  1. keep a database of all URLs
  2. when you insert a new URL into the database, find out the id of the auto-incrementing integer primary key.
  3. encode that integer into base 36 or 62 (digits + lowercase alpha or digits + mixed-case alpha). Voila! You have a short url!

Encoding to base 36/decoding from base 36 is simple in Ruby:

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

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

Encoding to base 62 is a bit tricker. Here's one way to do it:

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

...and here it is in action:

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

If you want to avoid URLs that happen to be English words (for example, four-letter swear words) you can use a set of characters that does not include vowels:

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

However, with this you still have problems like AnyBase.encode(328059,base31) or AnyBase.encode(345055,base31) or AnyBase.encode(450324,base31). You may thus want to avoid vowel-like numbers as well:

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

This will also avoid the problem of "Is that a 0 or an O?" and "Is that a 1 or an I?".

二智少女猫性小仙女 2024-11-22 04:49:43

我使用 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

I use the bitly gem. It's really simple.

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
孤云独去闲 2024-11-22 04:49:43

那么,您可以使用众多 u​​rl 缩短服务的 API 来生成短 URL。几乎所有的服务都提供 API 供您调用和缩短 url,这正是 twitter 客户端的做法。您应该查看特定网址缩短服务的网站以获取更多详细信息。

如果您想自己创建这样的服务,那也可以非常简单,您所需要做的就是在原始长网址和特殊短网址(由您生成)之间维护一个内部映射(在数据库中) 。当您收到对特定短网址的请求时,您应该能够从数据库获取原始长网址并将用户重定向到相同的网址。

Well you could generate short URLs by using the APIs of the so many url shortening services. Almost all of the services that are out there provide an API for you to be able to invoke and shorten the url's, that is exactly how the twitter clients do as well. You should check out the particular url shortening service's website for further details.

If you want to create such a service on your own, that also can be quite simple, all you need to do is essentially maintain an internal mapping (in a database) between the original long url and a special short url (generated by you). And when you receive a request for a particular short url, you should then be able to get the original long url from the database and redirect the user to the same.

池木 2024-11-22 04:49:43

对于 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

For Ruby 2.0, replace decode method by:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文