新浪微博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

Python模拟新浪微博登录

最近实验室的项目,需要一些真实的数据,而我们选择了从新浪微博抓取数据。对于新浪微博来说,只要登录了以后,微博以及关注和被关注等等信息才是可见的,所以要抓取,第一步是要模拟登录。

一开始,我打算按照这里的方法登录weibo.com并获取信息,但是发现新浪微博初始的页面的数据是放在JS中并以json格式存放的,页面加载的时候才渲染到HTML中,于是我解析了JS代码,证明此法可行,但是接下来遇到问题,因为我们打开新浪微博是不会一次性加载的,移到页面低端的时候才会加载一部分,这个很难模拟,虽然可以通过分析ajax数据得到,但是由于GET的参数多达十几个,这需要时间来分析这些参数的含义,这么做很麻烦。于是我想到,可以通过登录手机版的微博:weibo.cn来获取,而手机版的页面几乎没有JS,数据几乎都在HTML中,而且加载剩余的数据是通过分页进行的。

weibo.cn和weibo.com不是使用一种登录机制,下面直接贴出代码,代码的内容并不难,主要是登录的流程。

代码中用到了lxml库来解析HTML。Windows系统可以在这里下载二进制包。

马克聚的那点事儿

不晓得从什么时候开始,生活中开始充斥各种社交网络,知识的获取也比任何时候更方便。很多网站都有收藏的功能,对我来说,Google reader里订阅了一些feed,看到不错的文章,就习惯在上面加星;新浪微博里,我也会收藏一些不错的微博;我也常用收藏夹来保存一些不错的网站。

但是呢?相信很多人和我一样,把看到不错的东西收藏一下,就再也没碰过,比如在新浪微博上,经常看到同学转发微博,上面写着“mark”,下面会有人说,别马克了,你会看吗?不光不看,而且以后遇到类似的问题,会觉得在哪里看过,但是却又想不起来,于是只能再去google或者百度了,这真是时间和效率的双重浪费。

所以,我花了一个多月的时间在GAE上做了个小应用——马克聚,地址在:http://www.makeju.com,就是马克聚的拼音。登录需要使用Google账户。目前,马克聚实现了新浪微博收藏和Google Reader加星两处的马克来源,将来会支持更多。

从个人角度,我希望用马克聚能做到这些事情:

  • 分类:能够把mark的内容分门别类。
  • 加标签:以后可以通过标签寻找马克。
  • 打分:给内容评上重要程度,以后可以按重要的程度排序。
  • 提醒:提醒一个时间看,不要忘了。
  • 搜索:能够在所有马克的内容里寻找,遇到过的问题不用再问搜索引擎了。

当然,这些只是基本的,而目前的马克聚也只是最初的版本。它看起来和Google Reader很像,那是因为作为一个码农,对界面和用户体验部分不那么得心应手。不过,接下来,我想对马克聚有以下改造:

  • 从两栏的结构改成三栏,每一栏可以滚动,因为现在两栏的左边部分是fixed的,所以我只能通过限制添加分类的方式来避免高度过高;而且我希望能够展示多层级的分类。
  • 增加马克内容的备注功能,在阅读马克的内容的时候,可以对内容注释。
  • 国际化,支持英文的界面。

在我的计划里,我打算做一个Chrome插件和Android客户端,用Chrome插件可以把收藏夹的内容导入,而Android客户端显而易见,可以在手机上阅读马克的内容,还有就是收到阅读的提醒。

由于实验室的事情比较多,业余的时间有限,所以,我只能在有限的事情里来慢慢实现以上计划。

各位同学,如果你对马克聚有任何意见,或者有什么经常使用的马克的来源,别忘了告诉我,在文章的评论,博客留言板,或者马克聚的意见反馈,都可以。

最后,感谢舍友对马克聚所做的测试。

使用GAE的一些感受

最近个人的一个小项目部署在GAE上,项目写了也有一个多月,所以这篇文章就主要说说这一个多月来使用GAE的一些感受,也算是给想选择使用GAE的同学一些建议把。

其实GAE一点都不是什么新奇的东西,推出也有好几年了,不过由于众所周知的原因,国内访问不是很顺畅,appspot.com更是断得彻底,所以很多程序猿都不是很了解。其实,GAE就是云计算当中一个重要分支PaaS(平台即服务)的重要代表,你只需按照GAE提供的一系列API写好应用,upload上去,就可以访问了,服务器的事情都可以交给Google来处理,包括云的弹性和数据的存储等等。而Google方面也提供用户一些基础的配额,在这些配额之下,用户是无需任何花费的,不过如果应用如果需要更多的资源,那就需要付费了,好的地方是,你的应用瓶颈在哪里,你就可以只为那部分付费,这看起来确实节约了开销。

GAE访问不畅,国内类似的产品倒不少,比较知名的就是新浪的SAE和百度的BAE,这俩从名字上就明白了。SAE和GAE很类似,BAE看起来也差不多,不过,现在还在邀请使用的阶段,而我也没能拿到邀请码,所以哪位同学有多余的,可以分享给我一份,不胜感激:)

话休絮烦。使用下来的体会主要有以下几点:

使用GAE就意味着你的应用被限定在它的框架中,这是一把双刃剑。好处主要是方便,操作数据库可以使用datastore API而无需自己配置数据库;taskqueue也直接有API使用,异步的任务队列很轻松就搞定,而无需使用诸如Celery+RabbitMQ的解决方案;Channel API提供了类似客户端和服务器长连接的技术,它复用了GTalk的组件,会适配浏览器而选择使用WebSocket抑或是长轮询,你无需去了解它们的细节。这些当然只是例子,还有诸如cron job等等,它极大得简化了开发人员的工作,而不是让程序猿们花大量时间在配置上。

坏处也就是显而易见的了,由于大量使用GAE提供的接口,应用的可移植性就变得很差,如果一旦由于各种原因放弃使用GAE,整个程序面临着重写,当然将问题减少到最小的方法是使用适配器模式来做一层封装,不过还是有较大的工作量。

第二就是关于配额的的问题。其实在GAE部署应用了之后才能深刻体会到配额的数量真的不多,所以不可避免的做法就是在应用里处处精打细算,至少不能浪费。

首先是datastore的配额问题。在其免费配额中关于读操作有两项:“Datastore Read Operations”和:“Datastore Small Operations”,他们都有5万次/天的配额,不过千万别觉得Google慷慨,这个其实是很不经用的。不过相信很多人不明白什么是read和small,这里就先简单做个介绍。

对于datastore,每个要存储的model实体(相当于关系数据库中的行),都有个必有的key和可选的parent属性,通过它们就可以找到一个model实体,而parent是极其重要的,如果应用中用到了事务,不论是否跨model,只有拥有相同的祖先(ancestor)才可以完成一次事务。对于譬如一次查询操作,我们查询到了十个结果并返回这些model实体,那么我们就使用了11次read操作;更极端的是,如果查询的时候使用了offset,就是跳过了offset个结果,这些要是要算入到read操作中的,所以比如说取跳过50个的10个结果,这实际上就是61次read操作,所以开销是极大的。解决方法就是使用游标(cursor),每次查询的时候拿到上次查询的游标,从游标开始取10个,这样就还是11次操作。

那么什么是small操作呢,刚刚提到了model的key属性,我们通过key得到一个model实体,这就是1次small操作;还有就是count操作,比如说我们得到结果是100,那么就是1次的read操作+100次的small操作,因为计算数量不需要取到数据,只需要知道key就可以了。而我们查询结果的时候,可以只查询得到key,再通过key去得到model实体,这样就减少了read操作,但也相应增大了small操作。不过无论如何,都要记住游标是很重要的东西,它其实只是一个很长的字符串,所以在网页应用中,我们可以渲染到页面中,然后在之后的查询时,作为参数传递。

使用游标确实能减少配额,不过不能一劳永逸,那么怎么办呢?相信很多同学都想到了,当然是使用缓存(memcache)。因此可以说缓存在GAE中非常重要,因为缓存和配额没有关系,它的使用仅仅和内存的大小有关,所以几乎所有常用的数据都要放到缓存中,缓存的类型也可以包括model实体和页面等等的缓存。所以我们可以用工厂模式来操作数据库的增删查改,每个操作都和缓存结合起来。

关于配额还有一点就是Channel API,它的使用需要在用户访问时创建一个channel,而这个channel 2个小时就会失效。由于每天创建channel的个数为100,如果每次用户访问都需要创建channel,开销太大了,所以,我的做法还是将这个用户的channel缓存,并设置2个小时的失效时间。

好了,关于GAE使用的感受和心得,暂时就总结到这里。如果想到其他的,我会进行补充,以后也会对一些细节做一些分享。

Dart语言性能测试

在我之前的这篇文章中,将一个计算密集型的例子移植到了Go语言。这里,将同样的代码移植到了Dart语言,并与一些语言的结果进行了比较。

Dart是由Google开发的语言平台,主要用于编写web应用,它可以运行在服务器端和浏览器端(目前直接支持的只有Dartium:支持Dart VM的Chromium)。之所以称其为平台,是因为Dart包括了语言、基础库、一个编辑器(Dart Editor),一个可以运行在浏览器和服务器端的虚拟机,还包括一个将Dart语言编译至JavaScript的编译器(dart2js)。

Dart对开发人员还是比较友好的,拥有比较傻瓜式的开发环境;从语法的层面来说,Dart看上去是个语法糖版本的Java,所以,一个从事后端的Java程序员能够较快地上手。Dart推出的目的,是弥补JavaScript的一些不足,不过就目前来说,Dart想挑战大红大紫的JS,有很大难度。不过,在我看来,在Dart VM成熟以后,Google可以考虑将Dart移植到Android平台,这样,Chrome和Android就可以有统一的编程语言,Android平台本地程序也就可以容易地切换到web化,不过这一切的前提都是Dart取得一定成功,具体结果如何,还是让我们拭目以待吧。

现在还是回到测试上来,实验中,生成了256×256像素图片,每个像素点默认100次采样。

由于目前Dart处在早期开发阶段,所以随着时间的变化,本文结果可能有较大的变化。本文所使用的Dart SDK版本为10597。本实验Dart的代码托管在这里

实验环境是Visual studio2010/.net framwork 4.0编译,Intel core2 P7570(2.26GHz主频)。VC++编译器选项参照了原作者,而chrome浏览器版本为21.0.1180.60 m,Java版本为1.7.0_03,Go版本为1.0.2。

最终的实验结果如下:

语言运行时长(秒)比例
VC++(基准) 57.513 1.00x
Java 65.719 1.14x
C# 127.765 2.22x
JsChrome 266.616 4.64x
Go 310.695 5.40x
Dart 2819.643 49.03x

从表格中可以看到Dart的性能让人大跌眼镜,不过,Dart还处在早期阶段,在语法还没完全成型的阶段,对性能的要求就有些太苛刻了。无论如何,本文对Dart的性能的测试也只是一个参考,没有什么实际意义。很多时候,性能的瓶颈并不都在计算这块上。

最后,关于Google的另一个语言Go,可以看到在Go1发布了以后,性能方面还没有明显提高。不过和Dart不同,大家对Go的性能的期许会高很多,相信Go1后的Golang会越来越好吧。

Update:在最新版build 16323版下花费2319.813秒,还是比较慢的,不过有了一些改进。另外,由于Dart API发生了一些变化,所以代码做了些修正。

关于作者

残阳似血(@秦续业),程序猿一枚,把梦想揣进口袋的挨踢工作者。现加入阿里云,研究僧毕业于上海交通大学软件学院ADC实验室。熟悉分布式数据分析(DataFrame并行化框架)、基于图模型的分布式数据库和并行计算、Dpark/Spark以及Python web开发(Django、tornado)等。

博客分类

点击排行

标签云

扫描访问

主题

残阳似血的微博