最近碰到一件头痛的事。我需要下载看雪论坛的一些资料,因此去注册了一个账号。但为了获取认证码,需要一定的论坛积分,新手获取积分的方法有:技术性回帖、长时间在线。很懒的我显然会选择长时间在线,但论坛会检测在线状态,如果长时间没有更换浏览的页面,是不算在线的。
因此琢磨这件枯燥的事有没有别的办法解决。
最开始想到用wget和命令行脚本,尝试之后发现wget无法登陆到论坛(也许是我没找到方法)。具体地说,这个论坛是用post方法把用户名和密码用MD5加密发送到服务器端登陆,之后用cookies保持状态。用socket也许是可以做到的,不过还是觉得麻烦。
然后就想到了Google的Chrome浏览器可以自己开发插件(官方叫法是“扩展程序”)。花了一个下午的时间读文档、写代码和测试,终于搞定了。下面就是详细的介绍。
一、参考网页
1、Google Chrome Extensions开发首页
http://code.google.com/chrome/extensions/index.html
2、入门的例子
http://code.google.com/chrome/extensions/getstarted.html
3、开发者指南
http://code.google.com/chrome/extensions/devguide.html
二、程序分析
1、图标
通常需要至少两个png格式的图标,大小为19*19、48*48,分别显示在地址栏、扩展程序管理栏。我选用了一个简单的雪花图标:
2、manifest.json
扩展程序的主文件,代码如下:
{ "name": "Keep Active in bbs.pediy.com", "version": "0.2", "description": "Automatically keep a loginned user's status active in the forum bbs.pediy.com.", "icons": { "48": "icon48.png", "128": "icon128.png" }, "background_page": "background.html", "page_action": { "default_icon": "icon19.png" }, "permissions": [ "tabs" ], "content_scripts": [ { "matches": ["http://bbs.pediy.com/"], "js": ["visit.js"] } ] }
从字面上就可以看出,第2行是名称、第3行是版本号、第4行是描述,这几句是必须存在的。
第8行background_page也是(事实上)必须存在的,作用将在后面说明。
第10行是行为类型,有page_action和browser_action两种:
page_action针对某些具体页面作用,图标显示在该页面地址栏内的右侧(只在作用的页面显示);
browser_action针对整个浏览器作用,图标显示在地址栏外的右侧(工具栏图标那里)。
可以参考下面的图(从左往右是page_action的看雪插件、browser_action的Gmail提醒和Reader提醒插件):
browser_action中一个很重要的动作是popup,即鼠标点击时的动作,可以参考上面的第二个地址:入门的例子。
第13行premissions,其中的tabs是因为我们在程序中对Chrome的标签进行操作,调用了tabs下的函数。如果像“入门的例子”中那样调用了flickr.com等网站的开放API,还需要将API的引用地址加入进来。
第16行content_scripts描述对哪些页面采用什么脚本操作。
其中matches表明对哪些页面进行匹配。可以使用通配符*,但我这里设定只针对http://bbs.pediy.com产生作用,看雪论坛另一个URL是http://bbs.kanxue.com,暂时没有找到同时匹配这两个的方法。
js是匹配成功后,调用的执行脚本。
3、visit.js
在常规的插件中,content_scripts中指示的.js文件是实现插件功能的主要代码之一。
但我这里的visit.js只有一行代码:
chrome.extension.sendRequest();
它的作用是向扩展程序管理者发送一个请求消息。这个消息将被background.html捕获。
我将主要功能放到background.html中实现,是因为根据规定,.js只能调用chrome API中的一部分,而background.html不受这个限制。
4、background.html
代码如下:
<script type="text/javascript"><!--mce:0--></script>
其中,chrome.extension.onRequest.addListener捕获前面visit.js传来的请求消息以后,就开始执行后面的内容。
chrome.pageAction.show(sender.tab.id)在发送消息的tab上显示扩展程序图标。
chrome.windows.getCurrent定位到当前的Chrome窗口,通过winid = Win.id获取当前窗口ID。
接下来是一个函数circle(),它在要结束的时候延迟60秒调用自身,因而构成死循环。
这个函数先生成一个指向看雪论坛帖子的随机的URL,然后在前面的这个窗口里创建一个新的标签chrome.tabs.create,并在里面打开这个随机URL,selected:false表明不选定这个标签,因而做到不影响用户的正常使用,同时用tabid = Tab.id获取创建的这个标签的ID,最后关闭这个标签。
三、测试
在Chrome的扩展程序管理窗口,展开“开发人员模式”,点击“载入正在开发的的扩展模式”,可以方便的测试本地的程序。
四、发布扩展程序
在https://chrome.google.com/extensions/developer/dashboard发布完成的扩展程序。
最后,我的这个插件地址是:
https://chrome.google.com/extensions/detail/fdgcpjibiffgnfidocngbcijdfcaegel