新浪微博mid和url的互算
我们在使用新浪微博API时,有时需要得到一个微博的url,但是如statuses/public_timeline等接口中取得的微博status的字段中并没有包含。不过,status中包含了一个mid字段,通过mid,我们实际上是可以通过计算得到url的。
在开始计算之前有必要说明一下,什么是base62编码。它实际上就是十进制和62位进制的互换。对于62进制,从0数到9以后,10用小写字母a表示,接着数完26个字母,到z为35,然后36为大写字母A,一直到61为大写字母Z。所以,我们可以实现十进制数字base62编码的encode和decode。下面的代码实际上来自stackoverflow:
ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" def base62_encode(num, alphabet=ALPHABET): """Encode a number in Base X `num`: The number to encode `alphabet`: The alphabet to use for encoding """ if (num == 0): return alphabet[0] arr = [] base = len(alphabet) while num: rem = num % base num = num // base arr.append(alphabet[rem]) arr.reverse() return ''.join(arr) def base62_decode(string, alphabet=ALPHABET): """Decode a Base X encoded string into the number Arguments: - `string`: The encoded string - `alphabet`: The alphabet to use for encoding """ base = len(alphabet) strlen = len(string) num = 0 idx = 0 for char in string: power = (strlen - (idx + 1)) num += alphabet.index(char) * (base ** power) idx += 1 return num
下面先说url到mid的转换。对于一个新浪微博url,它是形如:http://weibo.com/2991905905/z579Hz9Wr,中间的数字是用户的uid,重要的是后面的字符串“z579Hz9Wr”。它的计算其实也很简单,从后向前四个字符一组,就得到:
z
579H
z9Wr
将每个字符串用base62编码来decode,就可以得到它们的十进制数字分别为:
35
1219149
8379699
将它们拼起来就可以得到mid为:“3512191498379699”。这里要强调的是:对于除了开头的字符串,如果得到的十进制数字不足7位,需要在前面补足0。比如得到的十进制数分别为:35,33040,8906190,则需要在33040前面添上两个0。
代码如下:
def url_to_mid(url): ''' >>> url_to_mid('z0JH2lOMb') 3501756485200075L >>> url_to_mid('z0Ijpwgk7') 3501703397689247L >>> url_to_mid('z0IgABdSn') 3501701648871479L >>> url_to_mid('z08AUBmUe') 3500330408906190L >>> url_to_mid('z06qL6b28') 3500247231472384L >>> url_to_mid('yCtxn8IXR') 3491700092079471L >>> url_to_mid('yAt1n2xRa') 3486913690606804L ''' url = str(url)[::-1] size = len(url) / 4 if len(url) % 4 == 0 else len(url) / 4 + 1 result = [] for i in range(size): s = url[i * 4: (i + 1) * 4][::-1] s = str(base62_decode(str(s))) s_len = len(s) if i < size - 1 and s_len < 7: s = (7 - s_len) * '0' + s result.append(s) result.reverse() return int(''.join(result))
mid转为url也就很简单了,对于一个mid,我们从后向前每7位一组,用base62编码来encode,拼起来即可。同样要注意的是,每7个一组的数字,除了开头一组,如果得到的62进制数字不足4位,需要补足0。
def mid_to_url(midint): ''' >>> mid_to_url(3501756485200075) 'z0JH2lOMb' >>> mid_to_url(3501703397689247) 'z0Ijpwgk7' >>> mid_to_url(3501701648871479) 'z0IgABdSn' >>> mid_to_url(3500330408906190) 'z08AUBmUe' >>> mid_to_url(3500247231472384) 'z06qL6b28' >>> mid_to_url(3491700092079471) 'yCtxn8IXR' >>> mid_to_url(3486913690606804) 'yAt1n2xRa' ''' midint = str(midint)[::-1] size = len(midint) / 7 if len(midint) % 7 == 0 else len(midint) / 7 + 1 result = [] for i in range(size): s = midint[i * 7: (i + 1) * 7][::-1] s = base62_encode(int(s)) s_len = len(s) if i < size - 1 and len(s) < 4: s = '0' * (4 - s_len) + s result.append(s) result.reverse() return ''.join(result)
运行doctest可以看到所有的测试用例都通过了。
最后其实我不太明白为什么新浪微博不直接把url包含在字段中,而新浪微博的开放平台也有很多不符合标准的地方,其实本文的内容并没有什么技术含量,不过就是让开发人员折腾一下。还有比如refresh token的问题等等,这里就不一一枚举了。
good! js的 weobo mid实现 https://github.com/node-modules/weibo-mid
发烧友某天把我从微博好友中删除了,心痛不已呀。现在我也来到了西厂,多交流哇。
学习了
计算你的工作,并试着知道你要去哪里。通过这种方式,我们知道我们在做什么。
我有个问题。请问博主是如何想到要把9个字符分为1、4、4这样的三组呢?如果是我,我就想不到
给作者留言
关于作者
残阳似血(@秦续业),程序猿一枚,把梦想揣进口袋的挨踢工作者。现加入阿里云,研究僧毕业于上海交通大学软件学院ADC实验室。熟悉分布式数据分析(DataFrame并行化框架)、基于图模型的分布式数据库和并行计算、Dpark/Spark以及Python web开发(Django、tornado)等。
博客分类
搜索
点击排行
标签云
扫描访问
主题
残阳似血的微博
登录