Google URL Shortener APIを利用する

goo.gl(6文字)。bit.ly(6文字)と同じというのが、対抗意識ばりばりというか、じゃあGoogleの強みとして述べているセキュリティとか速さをどれくらい体験出来るのかな、ということになる。

goo.gl短縮URLを作るための、APIは公開されていないのだが、Google Toolbarのxpiファイルをunzipし、lib/toolbar.js というファイルを読むと getUrlShorteningRequestParams_ という関数が見付かる。これが、Google URL Shortenerに投げるPOSTデータを生成している。

JavaScriptコードをPythonに変換してみた。関数名などは出来るだけそのままにしたが、一部は異なる記述を使っているので、JSコードを参照されたし。

#!/usr/bin/python

# import struct
import urllib
import simplejson

def _c(vals):
    l = 0
    for val in vals:
        l += val & 4294967295
    return l

def _d(l):
    if l <=  0:
        l += 4294967296
    m = str(l) 
    o = 0
    n = False
    for char in m[::-1]:
        q = int(char)
        if n:
            q *= 2
            o += q / 10 + q % 10  # JSだと Math.floor(q / 10) + q % 10
        else:
            o += q
        n = not(n)
    m = o % 10
    o = 0
    if m != 0:
        o = 10 - m
        if len(str(l)) % 2 == 1:
            if o % 2 == 1:
                o += 9
            o /= 2
    return str(o) + str(l)

def _e(uri):
    m = 5381
    for char in uri:
        # m = _c([m << 5, m, struct.unpack("B", char)[0]])
        m = _c([m << 5, m, ord(char)])
    return m

def _f(uri):
    m = 0
    for char in uri:
        # m = _c([struct.unpack("B", char)[0], m << 6, m << 16, -1 * m])
        m = _c([ord(char), m << 6, m << 16, -1 * m])
    return m

def _make_auth_token(uri):
    i = _e(uri)
    i = i >> 2 & 1073741823
    i = i >> 4 & 67108800 | i & 63
    i = i >> 4 & 4193280 | i & 1023
    i = i >> 4 & 245760 | i & 16383
    h = _f(uri)
    k = (i >> 2 & 15) << 4 | h & 15
    k |= (i >> 6 & 15) << 12 | (h >> 8 & 15) << 8
    k |= (i >> 10 & 15) << 20 | (h >> 16 & 15) << 16
    k |= (i >> 14 & 15) << 28 | (h >> 24 & 15) << 24
    j = "7" + _d(k)
    return j

def get_short_url(uri, user):
    if user is None:
        user = 'toolbar@google.com'
    token = _make_auth_token(uri)
    opt = 'user='+user+'&'+urllib.urlencode({'url':uri})+'&auth_token='+token
    # print opt
    ggl_url = 'http://goo.gl/api/url'
    res = urllib.urlopen(ggl_url, opt)
    # print res.read()
    short_url =  simplejson.loads(res.read())['short_url']
    return short_url

if __name__ == "__main__":
    print get_short_url("http://www.aida.t.u-tokyo.ac.jp/", None)
$ python googl.py
http://goo.gl/2YzP

Google Toolbarのアップデートに伴って使えなくなるかもしれないが、それまでエンジョイ。

  • -

2009/12/17追記:

JavaScriptの charCodeAt() はUnicodeを扱えるから、struct.unpack("B",char)は不適切。ていうか、ord() で良かった。