首先发个我的插件的地址:
Info Thief – 谷歌浏览器扩展程序库 (请用chrome浏览)
一个chrome扩展有几个基本的组成部分:
1.manifest.json文件.这是一个配置文件,扩展所需的配置信息都在这里配置.
2.popup.点击后将会在图标旁边弹出的一个小网页,每点击一次,页面执行一次,行为跟普通网页相同,可以包含js,css资源
3.background.这个页面在插件的整个生命周期都会一直存在着,它可以用来执行一些事件监听等用途.
4.content_scripts.这是一个js文件,在manifest.json文件中配置好了之后,在特定的页面里都会插入这段js,js可以使用被操作页面里dom,但是不能访问js环境.
5。其他几个类似:配置页面,Override页面.在此插件中没有涉及到,具体可以去看官方文档.
在开始制作程序之前,首先要熟悉manifest.json文件,这个文件里有很多配置信息,这些配置信息决定了程序的运行方式,而且如果稍微有一点地方配置错误,都会引起插件不被识别的错误.
下面我就以我昨天晚上做的一个插件为例子来说说怎么制作出一个猥琐的插件来.
chrome插件很容易上手,我是昨天下午天快黑的时候才开始看文档的,之后熬了一个通宵,就做出了第一个插件来,我想以后我还会做很多好玩的插件出来滴,嘿嘿…..
首先说说我这个插件是做什么的,都是什么功能.
Info Thief翻译成中文就叫做”信息小偷吧”,当然不是我来偷用户的信息,而是用户可以用来抓取网页上的信息,这个信息暂时就是指email地址,这个插件对于某些人来说是很有用滴,例如:某些求种子,求套图的帖子,ls可以用这个工具来一次性收集好所有回帖的email地址,然后给他们群发种子,当然我不鼓励这种很黄很暴力的应用方式,
还有一种场合,那就是如果你是一个专门发广告邮件的人,你可以用这个在网上搜罗email地址,然后最后把广告群发给他们,
好吧,我承认这个插件很邪恶,但是也有好的应用,例如:lz发了本好书,大家回帖求书,lz可以一下子群发给回帖的哥哥们等等.
有了功能需求,下面就是分析了.
这个插件中我需要每打开一个页面,程序就去匹配页面里的email地址,核心功能很简单,就是匹配email地址,一个正则表达式而已.但是要获取到页面的内容可就不是那么简单了,主要这里我们不涉及服务器逻辑,而只是一个单纯的本地插件.不能用服务器去读取网站源代码.
从一开始我就坚信,获取页面内容的api谷歌浏览器的扩展肯定支持,后来我找了半天,发现了两个api可以用来获取页面内容,第一个是:array of DOMWindow chrome.extension.getExtensionTabs(integer windowId) Returns an array of the JavaScript 'window' objects for each of the tabs running inside the current extension. If windowId is specified, returns only the 'window' objects of tabs attached to the specified window. Parameters windowId ( optional integer ) Returns ( array of DOMWindow ) Array of global window objectstab在chrome里指某个tab页面,在扩展中有一个tab对象,它包含一些有关tab的信息,但是不包含tab的页面内容,通过这个方法,可以用tabid来取得某个tab,tabid是程序随机分配的,而不是按顺序排列的.
tab中包含下列的信息,都属于标识性的信息,
tab在chrome里指某个tab页面,在扩展中有一个tab对象,它包含一些有关tab的信息,但是不包含tab的页面内容,通过这个方法,可以用tabid来取得某个tab,tabid是程序随机分配的,而不是按顺序排列的.
tab中包含下列的信息,都属于标识性的信息,这个可以在任何页面获取到当前活动tab的window对象,可以指定返回某一个,也可以返回一个数组.这里理解错了,待我再看看
tab在chrome里指某个tab页面,在扩展中有一个tab对象,它包含一些有关tab的信息,但是不包含tab的页面内容,通过这个方法,可以用tabid来取得某个tab,tabid是程序随机分配的,而不是按顺序排列的.
tab中包含下列的信息,都属于标识性的信息,Types Tab ( object ) id ( integer ) The ID of the tab. Tab IDs are unique within a browser session. index ( integer ) The zero-based index of the tab within its window. windowId ( integer ) The ID of the window the tab is contained within. selected ( boolean ) Whether the tab is selected. url ( string ) The URL the tab is displaying. title ( optional string ) The title of the tab. This may not be available if the tab is loading. favIconUrl ( optional string ) The URL of the tab's favicon. This may not be available if the tab is loading. status ( optional string ) Either loading or complete. incognito ( boolean ) Whether the tab is in an incognito window.上面这个方法不是入侵式的,使用起来比较方便,在插件的任何地方都可以调用,但是实际使用的时候,我发现当遍历当前所有的tab的时候,浏览器立即崩溃掉,要求重启.也就是说可能操作太复杂,浏览器承受不住,这里要说一下chrome的插件机制,我本来以为chrome从底层封装了一下,结果发现性能和单纯的浏览器浏览差异非常大,性能极其差,应用动画的话,卡的很.
这个方法可以说是不行了,别急,下面拉出一个很重要的概念:Content Scripts.
Content Scripts是个很好玩,很实用,的东西,利用它你可以向所有的页面插入css,js等东西,这样也造成一些安全隐患,所以对于js侵入来说,不可以在插入的js中访问原页面里的js环境,只能访问页面的DOM,然而这对我们来说已经足够了.接下来,我们的实现就是向每个页面都插入一小段js,这段js获取页面的document.body.innerHTML.然后对获取到的内容进行正则匹配,最后得到一个含有匹配结果的数组.之后我们通过通信机制把数组传回插件的background页面进行处理
要做到这一步,要做如下工作:
1..配置manifest.json文件(带有详细解释){ "name": "Info Thief", //插件名称 "version": "1.2", //插件版本,很重要,升级的时候必备,而且每次升级的版本号都必须要增加 "icons": { "48": "icon.png", //图标 "128": "icon.png" }, "description": "**", //简介 "browser_action": { //浏览器行为 "default_icon": "icon.png", //默认显示的图标 "default_title":"运行中", //鼠标移上去时显示的tip "default_popup":"index.html" //鼠标点击图标时候弹出的页面,这个页面是自适应的 }, "permissions": [ "tabs","http://*/" ], //对tab的url进行正则过滤 "background_page":"check.html", //background页面,这个页面运行于整个生命周期 "content_scripts": [ //要插入页面的脚本 { "matches": ["http://*/*"], //过滤页面 "js": ["content.js"], //插入的js "run_at":"document_start"//什么时候运行,这里设置成页面加载前运行,以便在页面加载过程中能制造出正在加载的样式 } ] }
接下来我们创建一个content.js,它将会被插入每个页面中,然后获取内容
window.addEventListener("load",function(){
//提取邮箱地址,后来发现这个正则并不完美,后续需要改进,无法匹配@后面有两个.的情况
var reg=new RegExp("[0-9a-zA-Z_][0-9a-zA-Z_\.]*?\@[0-9a-zA-Z]*?\\.[0-9a-zA-Z]*","g"),cache,result=[],
//获取dom元素内容
source=document.body.innerHTML
var has=function(arr,item){
for(var i=0,j=arr.length;i<j;i++){
if(arr[i]==item) return true;
}
return false;
}
var time=new Date()
time=time.getTime();
//执行匹配,设定时间限制,防止执行时间过长
while((cache=reg.exec(source))!=null){
has(result,cache[0])||result.push(cache[0])
var time2=new Date()
time2=time2.getTime();
if((time2-time)>=5000) break;
}
//和extension页面通信,result数组将被发送到background页面,数据格式也不会被改变
chrome.extension.sendRequest({
emails:result
});
});
接着是background页面,我将它命名为:check.html:
//监听事件,接收消息
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if(request.isSearching){
//创建正在执行的动画效果
interCount=0
interval=setInterval(function(){
switch(interCount%4){
case 0: chrome.browserAction.setBadgeText({text:"· "});break;
case 1: chrome.browserAction.setBadgeText({text:" · "});break;
case 2: chrome.browserAction.setBadgeText({text:" · "});break;
case 3: chrome.browserAction.setBadgeText({text:" · "});break;
case 4: chrome.browserAction.setBadgeText({text:" ·"});break;
}
interCount++
if(interCount>100){
clearInterval(interval);
if(localStorage["emails"]) var emails=(localStorage["emails"]).split(",")
else var emails=[]
resultCount=emails.length
chrome.browserAction.setBadgeText({text:resultCount.toString()})
}
},100)
}else{
//将取到的email地址去重后加入到localStorage里
if(localStorage["emails"]) var emails=(localStorage["emails"]).split(",")
else var emails=[]
M.Array.each(request.emails,function(i){
if(!M.Array.has(emails,i)){
emails.push(i)
}
})
resultCount=emails.length
emails=emails.join(",")
localStorage["emails"]=emails
interval&&clearInterval(interval)
//更新图标标签显示的字符
chrome.browserAction.setBadgeText({text:resultCount.toString()})
}
});
然后我们需要把结果展示给用户,就要用到popup了:
这个页面和其他页面是分离的,取数据的时候是从localStorage里面取的,没有什么特殊功能,只是展示一下而已.
至此,我们的插件就开发完成了,在开发的过程中可以用chrome随时调试,包括载入测试和单独页面的测试,具体可以看官方开发文档.开发完成后就可以发布了,发布的过程很简单,就是打包,然后上传,填写信息而已,没有什么特殊的操作…
http://www.beiju123.cn/blog


二十六公斤 · 2010年05月4日于3:57 上午
这个插件真不错··可惜我的浏览器似乎无效···
点击S无反应··
ilin · 2010年05月5日于9:03 下午
有点不足。识别地址只能识别类似xx@xxx.com.
如果是。xx@.co.uk截取到xx@.co 而已
Admin comment by admin · 2010年05月5日于11:29 下午
是的,我没料到这种比较特殊的地址
ilin · 2010年05月6日于11:55 下午
博主帮你想出来了哈,问了朋友,RegExp方法换成这个就获取得到了
[0-9a-zA-Z_][0-9a-zA-Z_\.]*?\@[0-9a-zA-Z]*?\\.[0-9a-zA-Z\.]*[0-9a-zA-Z\.]*?
ailien · 2010年05月12日于10:36 下午
博主,没有index.html的代码吗,chrome载入后提示找不到index.html,请问怎么解决?
Admin comment by admin · 2010年05月12日于10:58 下午
表copy这里的代码,你直接下了这个插件 ,然后解压那个包,就可以看到源代码了
ailien · 2010年05月12日于11:23 下午
博主,点击图标后index.html显示乱码?
Admin comment by admin · 2010年05月12日于11:26 下午
不是啊,你是不是把编码弄错了?文本文件编码改成utf-8
ailien · 2010年05月13日于2:44 上午
博主,能不能把这个插件的源码发给我一下啊,我按你的步骤来做了,但好像少了css和一些其他的东西,我要做一个Demo交上去,周末花个通宵来仔细搞下。谢了啊,我邮箱是:984166330@qq.com
ailien · 2010年05月13日于2:45 上午
“你直接下了这个插件 ,然后解压那个包,就可以看到源代码了”
只找到那个background.html了呀