[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 秒或更久,有明显的延迟 =.=