豆瓣系列专题[一]

背景

从大一开始认识豆娘到现在,发现蛮喜欢她的,做了两年多的知识记录,回过头来看,内心满是踏实的感觉。泡了两年,豆娘也是一路风雨兼程。一直想给这么个产品写自己的体验,见证豆娘的美丽和成熟,不过每每下笔,又怕人笑幼稚,好吧,就酱紫,不许笑,难得有机会去写这么一个系列的体验。(如果你对豆瓣不太了解的话,先看看豆瓣的发展历程,这样对豆瓣会清晰点。我对豆瓣的理解是,她是一个以书、影、音分享为主的知识型社区,以兴趣聚合同好。当然阿北的想法我是无法猜测的……)

我说广场

我说广场是豆瓣书、影、音资源的一个流通场所,在小站、阿尔法城出现之前,它承担着用户互动、信息流通等重任。

我觉得比较有趣的地方,是豆瓣对用户之间的互动所采取的策略。

douban image

在图 1_1 里面我们可以看到,用户发布相片和推荐网址这两种行为,用户的互动性是不同的。基于豆瓣资源的推荐,豆瓣鼓励用户去消费,而不是简单的互动,所以这里是没有 “回应” 动作的。

但作为一个社区来讲,这样不太合理。无论是用户的行为,还是用户的资源推荐,其实作为社区中的我们都会有好奇心,都有互动的愿望,应该鼓励用户的互动行为,“回应” 是很好的动作,但如果有其他的互动动作会不会更好呢?比如 facebook 的用户互动行为。

facebook content

facebook 的 “赞”、“评论”、“分享”

我关注的人和关注我的人

douban followers page

我关注和关注我的人都是豆瓣里面比较被人忽视的两个页面,但对于我来说,我觉得这两个页面蛮重要的。

观察过我同学用豆瓣的行为,和我自己使用的经验,这个页面的作用我觉得有两个:

  1. 个人通信录
  2. 管理自己的信息来源

但其实,我会有这样的需求,我会想了解我关注的人,他,都关注了谁。显然,图 2_1 无法满足这样的需求。让我们看看 twitter 是怎么做的?

在 follow 页面,无论是我 follow 的,还是 follow 我的,twitter 都会显示有效的用户信息,即用户的 description 名字头像
,去掉干扰的信息 (比如国内围脖比较喜欢的年龄、性别、跟随者个数这样的无效信息)。在信息的隐藏方面,当用户有意愿想去进一步了解对方的时候,点击一下对方的按钮,就会在右部窗口打开用户的详细信息。

可以看到,这样的页面有助于用户去方便快捷地了解到 follower 对象的信息,帮助用户获得优质的信息来源。

豆瓣的消息提醒机制

豆瓣社区的用户之间的互动不是实时的,而且豆瓣也缺乏这样的实时的沟通机制。

另外,用户是基于兴趣聚合起来,而不是像 facebook 那样的熟人网络构建起来的,互动性相对较弱。

所以,用户在这样的社区里面,会有种虚无的存在感。

我想到的一些解决方案,可以参考 twitter 和国内的一些围脖网站的做法。利用 Ajax 技术,异步调回最新的数据信息,利用声音提醒之类的,提示用户豆瓣主页有信息,用户可以不用刷新,减少体验的痛感。

twitter ajax

豆列

我喜欢豆娘一个很重要很重要的原因是她有豆列,可以帮我更好的做知识整理。但反观豆列的操作,我觉得可以有改进的余地,一个页面可以完成的操作,分成 3 个页面去做实在让人费解。虽然豆娘用不方便表达了自己希望优质的愿望,但对于有心想加书的人来说,真是件苦事。

[GM] 豆瓣图书插件

Update: 本插件已经失效了,短期内不会再更新了…… 亲,不要用这个来学习前端或者有关后台的知识

背景

在看了华科和 Light 几位师兄做的一个插件,基于 GM 和 FF
在豆瓣看书的同时,可以显示自己学校图书馆有没库存的信息。觉得这样的插件蛮实用的,
而且实现上也不会太难,就自己尝试做了一个。下面的内容就来讲解下相关的思路,以及我在做这个插件的过程中一些收获,特别是正则表达式和编码转换的理解,算是对自己这几天的一个小小总结。

preview of douban_GDUT

<插件效果示意图>

其实这个基于 GM 的脚本基本的思路可以用下面这张图来描述,下面将针对每个环节,具体讲下的一些实现原理和参考的资料。

豆瓣插件流程图

第一步:豆瓣 ====> 华科

在浏览器客户端这边,利用 GM 扩展程序本身提供的 JQ 库抽取豆瓣页面上的书籍信息,这里我们抽取两类,一个是书籍的 isbn 信息,另外一个就是标题信息。大家可能会很好奇为什么会有华科,这是因为学校图书馆不支持缺省’-’字符的 isbn 字符串查找,简单的说就是非常不智能,所以绕道华科的图书馆,借用他们的图书馆资源进行查找。

步骤

  1. 豆瓣页面:页面 DOM 树下载完毕后,利用 GM 本身提供的 jq 库,获取书籍标题和 isbn 信息
  2. 通过 GM 本身的 GM_xmlhttpRequest 异步调用,向 PHP 后台程序发出请求
  3. 服务器获取信息后,调用 fsockopen 函数,发起第一次查询,读入华科图书馆的内容页信息
  4. 利用强大的正则匹配,找到格式化的 isbn,截取之,返回数据
  5. 完成第一步

PS:这里面截取图书馆的信息的方法有非常多了,还可以利用 simplehtmldom 这样的 php 类库,简化抽取的工作量和效率;或者利用 php 本身的扩展 CURL 进行读入工作,不过我都没试,以后有机会再尝试好了。

第二步:华科 ====> 广工

拿到格式化后的 isbn,服务器再利用 fsockopen 发起第二次访问,不过这次的对象是广工的图书馆,因为单纯的使用正则匹配,所以遇到新的 html 页面,又要重新匹配过,难点是正则的表达式书写,在这个过程中,终于认识到了 php 数组和字符串函数的强大之处。

因为拿到 isbn 查询的时候,只能取到模糊搜索结果的页面,无法抽取一些具体的书籍信息。但这个时候匹配的结果只有一个,利用正则把书籍的 <a> 链接地址抽取出来,工作就完成了。

步骤

  1. 服务器利用 fsockopen 发起第二次访问,获取模糊查找页面的内容
  2. 正则匹配结果条目的 <a> 标签,抽取跳转地址
  3. 完成

第三步:广工 ====> 广工

终于拿到具体书目的详细地址了,大家在看前面的功能截图时候应该会留意到,我们要抽取的信息大概有 “馆藏地址”、“索引号”、“借阅状态” 3 种,正则抽取方面难度蛮大的,可能用之前介绍的类库来提取会更容易点。

步骤

  1. 服务器利用 fsockopen 发起第三次访问,获取具体书籍页面的内容
  2. 正则匹配相应条目
  3. 调用 Php 的数组和字符串函数,生成相应的内容块
  4. 写成 json 格式的字符串,返回给客户端
  5. 到这里,工作基本完成了

第四步:广工 ====> 豆瓣

回到豆瓣后,其实只是完成一个异步调用的过程,但这个时候通过返回的 json 格式字符串,js 利用 eval 函数可以生成对应的对象,然后通过遍历对象的属性,生成 html 字符串,动态插入到页面中去,并且套用豆瓣页面本身的 css 格式。

步骤

  1. 客户端在接受到返回信息后,调用 js 脚本
  2. 利用 eval () 函数生成对象,遍历产生对应的 html 内容
  3. 插入到页面中
  4. 整个工作到此完成

第五步:关于之后的反思

  1. 做的过程中遇到的困难
    • 一开始对 curl、fopen、fsockopen 等方法不了解,
      摸索了半天,最终还是一位做论坛的前辈指点,用 fsockopen 函数发起服务端的访问,解决了内容提取的难题。
    • 正则表达式写得不够强壮,在测试某些非常旧的书的时候,出现内容获取错误,或测试时间过长,需要不断验证自己的表达式,耗费了相当多的时间。
    • 不懂应用一些成熟的类库,增加了自己的工作量。
    • 最后生成的跳转链接有问题,没意识到 utf8 和 gb2312 格式对 URIencode 转换的效果是不一样的,对自己的问题的界定不够清晰,导致很多时候看的资料不是要解决的问题需要的…… 囧,说得好绕口……
    • 对 json 格式不熟悉,反复考量了半天才想出构造字符串的方法生成对象……
    • 严重缺乏想象力和创造力……
  2. 一些值得关注的事情
    • 在做这个的过程中,看了满多的东西,特别是关于书籍管理在 web2.
      0 时代的一些变革,关于这些有趣的思考可以关注豆瓣读书、libraything。你是否意识到到了书籍在网上不再是按照某个主题被聚合在一起了呢?
      他们有更多组合的可能,你其实有机会去实现某些有趣的组合。
    • 其实有很多人在挖掘图书馆资源方面已经做了很多的努力,比如说这个插件小组,还有 06 年就开始有的一个叫做 libraryLookup 的项目,可以输入你的图书馆信息,然后生成 bookmarketlet,挂在浏览器的标签栏上,你就可以通过弹窗查看馆藏信息了。
    • GM 很强大,关于 js 的很多想象都可以借助它来完成,比如……
  3. 最后的最后
    • 谢谢芬姐第一个试用,并给出最大的反馈
    • 谢谢聪的 js 建议,改动了前辈的一些代码
    • 其实这个 php 的后台程序可能没有太多的挑战,但我去做的原因可能是因为觉得这样的程序和脚本居然可以借助 GM 这样的扩展,做到获取不同地方书籍信息同步,节省多余的查找操作…… 我觉得自己是被这样的想法震撼了,所以才决定去做。

相关资源链接

  • 开始你自己的 GM 脚本开发:Get Started With Greasemonkey
  • 如果你喜欢豆瓣,又懂技术的话,又喜欢读书社区的话,豆瓣插件小组可能会比较合适
  • 在线正则匹配:基于 js 的 regexpa。不过注意 PHP 是 perl 和 posix 风格的,两者有区别的
  • Douban_GDUT 脚本和后台 PHP 代码地址:douban_GDUT

安装方法

  1. 安装 firefox
  2. 安装 GreaseMonkey 扩展程序
  3. 安装基于 GM 的 js 脚本
  4. 好了,打开你喜欢的豆瓣,看看有哪些书可以借阅的:-D

PS: 版本现在还不稳定,大家帮忙测试下,或者写个更好的后台,把效率提高起来,现在基本访问的速度都要 3-4 秒或更久,有明显的延迟 =.=