chrome插件扩展脚本开发01

系列文章目录

02_消息通信
03_注入JS、chromeAPI应用



前言

  • 最近接了个爬数据的项目,爬某大站,但爬取量小且不要求速度,寻思不如研究这个路线应该稳定得多,之后可能还会做成面向个人的小工具(已经临阵磨枪做了一个简单的,这里准备系统化研究下做个像样点的)

参考页面

【干货】Chrome插件(扩展)开发全攻略v2版本
chrome插件开发官方文档v3版本


一、Chrome扩展脚本目录介绍

manifest.json (全局配置)

  • 这是一个Chrome插件最重要也是必不可少的文件,用来配置所有和插件相关的配置,必须放在根目录。其中,manifest_versionnameversion3个是必不可少的,descriptionicons是推荐的。
  • 常见配置如下,全部配置看这里👉https://developer.chrome.com/extensions/manifest
    {
    	// 清单文件的版本,这个必须写,而且必须是2
    	"manifest_version": 2,
    	// 插件的名称
    	"name": "demo",
    	// 插件的版本
    	"version": "1.0.0",
    	// 插件描述
    	"description": "简单的Chrome扩展demo",
    	// 图标,一般偷懒全部用一个尺寸的也没问题
    	"icons":
    	{
    		"16": "img/icon.png",
    		"48": "img/icon.png",
    		"128": "img/icon.png"
    	},
    	// 会一直常驻的后台JS或后台页面
    	"background":
    	{
    		// 2种指定方式,如果指定JS,那么会自动生成一个背景页
    		"page": "background.html"
    		//"scripts": ["js/background.js"]
    	},
    	// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
    	"browser_action": 
    	{
    		"default_icon": "img/icon.png",
    		// 图标悬停时的标题,可选
    		"default_title": "这是一个示例Chrome插件",
    		"default_popup": "popup.html"
    	},
    	// 当某些特定页面打开才显示的图标
    	/*"page_action":
    	{
    		"default_icon": "img/icon.png",
    		"default_title": "我是pageAction",
    		"default_popup": "popup.html"
    	},*/
    	// 需要直接注入页面的JS
    	"content_scripts": 
    	[
    		{
    			//"matches": ["http://*/*", "https://*/*"],
    			// "<all_urls>" 表示匹配所有地址
    			"matches": ["<all_urls>"],
    			// 多个JS按顺序注入
    			"js": ["js/jquery-1.8.3.js", "js/content-script.js"],
    			// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
    			"css": ["css/custom.css"],
    			// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
    			"run_at": "document_start"
    		},
    		// 这里仅仅是为了演示content-script可以配置多个规则
    		{
    			"matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],
    			"js": ["js/show-image-content-size.js"]
    		}
    	],
    	// 权限申请
    	"permissions":
    	[
    		"contextMenus", // 右键菜单
    		"tabs", // 标签
    		"notifications", // 通知
    		"webRequest", // web请求
    		"webRequestBlocking",
    		"storage", // 插件本地存储
    		"http://*/*", // 可以通过executeScript或者insertCSS访问的网站
    		"https://*/*" // 可以通过executeScript或者insertCSS访问的网站
    	],
    	// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
    	"web_accessible_resources": ["js/inject.js"],
    	// 插件主页,这个很重要,不要浪费了这个免费广告位
    	"homepage_url": "https://www.baidu.com",
    	// 覆盖浏览器默认页面
    	"chrome_url_overrides":
    	{
    		// 覆盖浏览器默认的新标签页
    		"newtab": "newtab.html"
    	},
    	// Chrome40以前的插件配置页写法
    	"options_page": "options.html",
    	// Chrome40以后的插件配置页写法,如果2个都写,新版Chrome只认后面这一个
    	"options_ui":
    	{
    		"page": "options.html",
    		// 添加一些默认的样式,推荐使用
    		"chrome_style": true
    	},
    	// 向地址栏注册一个关键字以提供搜索建议,只能设置一个关键字
    	"omnibox": { "keyword" : "go" },
    	// 默认语言
    	"default_locale": "zh_CN",
    	// devtools页面入口,注意只能指向一个HTML文件,不能是JS文件
    	"devtools_page": "devtools.html"
    }
    

content-scripts (给页面注入js / css,无法被DOM调用)

  • 所谓content-scripts,其实就是Chrome插件中向页面注入脚本的一种形式(虽然名为script,其实还可以包括css的),借助content-scripts我们可以实现通过配置的方式轻松向指定页面注入JS和CSS(如果需要动态注入,可以参考下文),最常见的比如:广告屏蔽、页面CSS定制,等等。
  • 官方介绍 https://developer.chrome.com/extensions/content_scripts
  • 示例配置:
    {
    	// 需要直接注入页面的JS
    	"content_scripts": 
    	[
    		{
    			//"matches": ["http://*/*", "https://*/*"],
    			// "<all_urls>" 表示匹配所有地址
    			"matches": ["<all_urls>"],
    			// 多个JS按顺序注入
    			"js": ["js/jquery-1.8.3.js", "js/content-script.js"],
    			// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
    			"css": ["css/custom.css"],
    			// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
    			"run_at": "document_start"
    		}
    	],
    }
    
  • 特别注意,如果没有主动指定run_atdocument_start(默认为document_idle),下面这种代码是不会生效的:
    document.addEventListener('DOMContentLoaded', function()
    {
    	console.log('我被执行了!');
    });
    
  • content-scripts和原始页面共享DOM,但是不共享JS,如要访问页面JS(例如某个JS变量),只能通过注入js来实现。content-scripts不能访问绝大部分chrome.xxx.api,除了下面这4种:
    • chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest)
    • chrome.i18n
    • chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage)
    • chrome.storage
  • 其实看到这里不要悲观,这些API绝大部分时候都够用了,非要调用其它API的话,你还可以通过通信来实现让background来帮你调用(关于通信,后文有详细介绍)。

background (类似main)

  • 后台(姑且这么翻译吧),是一个常驻的页面,它的生命周期是插件中所有类型页面中最长的,它随着浏览器的打开而打开,随着浏览器的关闭而关闭,所以通常把需要一直运行的、启动就运行的、全局的代码放在background里面。
  • background的权限非常高,几乎可以调用所有的Chrome扩展API(除了devtools),而且它可以无限制跨域,也就是可以跨域访问任何网站而无需要求对方设置CORS。

    经过测试,其实不止是background,所有的直接通过chrome-extension://id/xx.html这种方式打开的网页都可以无限制跨域。

  • 全局配置``中,background可以通过page指定一张网页,也可以通过scripts直接指定一个JS,Chrome会自动为这个JS生成一个默认的网页:
    {
    	// 会一直常驻的后台JS或后台页面
    	"background":
    	{
    		// 2种指定方式,如果指定JS,那么会自动生成一个背景页
    		"page": "background.html"
    		//"scripts": ["js/background.js"]
    	},
    }
    
  • 需要特别说明的是,虽然你可以通过chrome-extension://xxx/background.html直接打开后台页,但是你打开的后台页和真正一直在后台运行的那个页面不是同一个,换句话说,你可以打开无数个background.html,但是真正在后台常驻的只有一个,而且这个你永远看不到它的界面,只能调试它的代码。

event-pages (通过事件加载/关闭的js)

  • 这里顺带介绍一下event-pages,它是一个什么东西呢?鉴于background生命周期太长,长时间挂载后台可能会影响性能,所以Google又弄一个event-pages,在配置文件上,它与background的唯一区别就是多了一个persistent参数:
    {
    	"background":
    	{
    		"scripts": ["event-page.js"],
    		"persistent": false
    	},
    }
    
  • 它的生命周期是:在被需要时加载,在空闲时被关闭,什么叫被需要时呢?比如第一次安装、插件更新、有content-script向它发送消息,等等。
  • 除了配置文件的变化,代码上也有一些细微变化,个人这个简单了解一下就行了,一般情况下background也不会很消耗性能的。

popup (插件的菜单界面)

  • popup是点击browser_action或者page_action图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。
  • popup可以包含任意你想要的HTML内容,并且会自适应大小。可以通过default_popup字段来指定popup页面,也可以调用setPopup()方法。
  • 配置方式:
    {
    	"browser_action":
    	{
    		"default_icon": "img/icon.png",
    		// 图标悬停时的标题,可选
    		"default_title": "这是一个示例Chrome插件",
    		"default_popup": "popup.html"
    	}
    }
    
  • 需要特别注意的是,由于单击图标打开popup,焦点离开又立即关闭,所以popup页面的生命周期一般很短,需要长时间运行的代码千万不要写在popup里面。
  • 在权限上,它和background非常类似,它们之间最大的不同是生命周期的不同,popup中可以直接通过chrome.extension.getBackgroundPage()获取background的window对象。

注入js脚本方法二 (可以被DOM调用)

  • 指的是通过DOM操作的方式向页面注入的一种JS。为什么要把这种JS单独拿出来讨论呢?又或者说为什么需要通过这种方式注入JS呢?
  • 这是因为content-script有一个很大的“缺陷”,也就是无法访问页面中的JS,虽然它可以操作DOM,但是DOM却不能调用它,也就是无法在DOM中通过绑定事件的方式调用content-script中的代码(包括直接写onclickaddEventListener2种方式都不行,操难怪之前这坑我怎么踩都踩不明白),但是,“在页面上添加一个按钮并调用插件的扩展API”是一个很常见的需求,那该怎么办呢?其实这就是本小节要讲的。
  • 在content-script中通过DOM方式向页面注入代码方法二示例:
    // 通过配置content-script向页面注入JS
    function injectCustomJs(jsPath)
    {
    	jsPath = jsPath || 'js/inject.js';
    	var temp = document.createElement('script');
    	temp.setAttribute('type', 'text/javascript');
    	// 获得的地址类似:chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js
    	temp.src = chrome.extension.getURL(jsPath);
    	temp.onload = function()
    	{
    		// 放在页面不好看,执行完后移除掉
    		this.parentNode.removeChild(this);
    	};
    	document.head.appendChild(temp);
    }
    
  • 你以为这样就行了?执行一下你会看到如下报错:
Denying load of chrome-extension://efbllncjkjiijkppagepehoekjojdclc/js/inject.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
  • 意思就是你想要在web中直接访问插件中的资源的话必须显示声明才行,manifest.json配置文件中增加如下:
{
	// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
	"web_accessible_resources": ["js/inject.js"],
}
  • 至于这种方式t如何调用content-script中的代码,后面我会在专门的一个消息通信章节详细介绍。(使用chromeAPI收发消息)

二、Chrome扩展脚本的8种展示形式

browserAction(浏览器右上角)

  • 通过配置browser_action可以在浏览器的右上角增加一个图标,一个browser_action可以拥有一个图标,一个tooltip,一个badge和一个popup
  • 示例配置如下:
    "browser_action":
    {
    	"default_icon": "img/icon.png",
    	"default_title": "这是一个示例Chrome插件",
    	"default_popup": "popup.html"
    }
    

图标

  • browser_action图标推荐使用宽高都为19像素的图片,更大的图标会被缩小,格式随意,一般推荐png,可以通过manifestdefault_icon字段配置,也可以调用setIcon()方法。

tooltip (鼠标悬停图标时显示的简介)

  • 修改browser_actionmanifestdefault_title字段,或者调用setTitle()方法。
  • 在这里插入图片描述

badge (图标上出现字,类似微信新消息的红豆)

  • 所谓badge就是在图标上显示一些文本,可以用来更新一些小的扩展状态提示信息。因为badge空间有限,所以只支持4个以下的字符(英文4个,中文2个)。badge无法通过配置文件来指定,必须通过代码实现,设置badge文字和颜色可以分别使用setBadgeText()setBadgeBackgroundColor()
  • ep:
    chrome.browserAction.setBadgeText({text: 'new'});
    chrome.browserAction.setBadgeBackgroundColor({color: [255, 0, 0, 255]});
    
  • 在这里插入图片描述

pageAction(地址栏右侧)

  • 所谓pageAction,指的是只有当某些特定页面打开才显示的图标,它和browserAction最大的区别是一个始终都显示,一个只在特定情况才显示。
  • 需要特别说明的是早些版本的Chrome是将pageAction放在地址栏的最右边,左键单击弹出popup,右键单击则弹出相关默认的选项菜单:在这里插入图片描述
  • 而新版的Chrome更改了这一策略,pageAction和普通的browserAction一样也是放在浏览器右上角,只不过没有点亮时是灰色的,点亮了才是彩色的,灰色时无论左键还是右键单击都是弹出选项:

    具体是从哪一版本开始改的没去仔细考究,反正知道v50.0的时候还是前者,v58.0的时候已改为后者。

  • 调整之后的pageAction我们可以简单地把它看成是可以置灰的browserAction
  • chrome.pageAction.show(tabId) 显示图标
  • chrome.pageAction.hide(tabId) 隐藏图标
  • 示例(只有打开百度才显示图标):
// manifest.json
{
	"page_action":
	{
		"default_icon": "img/icon.png",
		"default_title": "我是pageAction",
		"default_popup": "popup.html"
	},
	"permissions": ["declarativeContent"]
}

// background.js
chrome.runtime.onInstalled.addListener(function(){
	chrome.declarativeContent.onPageChanged.removeRules(undefined, function(){
		chrome.declarativeContent.onPageChanged.addRules([
			{
				conditions: [
					// 只有打开百度才显示pageAction
					new chrome.declarativeContent.PageStateMatcher({pageUrl: {urlContains: 'baidu.com'}})
				],
				actions: [new chrome.declarativeContent.ShowPageAction()]
			}
		]);
	});
});
  • 效果图:在这里插入图片描述

右键菜单

  • 通过开发Chrome插件可以自定义浏览器的右键菜单,主要是通过chrome.contextMenusAPI实现,右键菜单可以出现在不同的上下文,比如普通页面、选中的文字、图片、链接,等等,如果有同一个插件里面定义了多个菜单,Chrome会自动组合放到以插件名字命名的二级菜单里,如下:在这里插入图片描述
  • 最简单的右键菜单示例
// manifest.json
{"permissions": ["contextMenus"]}

// background.js
chrome.contextMenus.create({
	title: "测试右键菜单",
	onclick: function(){alert('您点击了右键菜单!');}
});
  • 示例:框选文字后的右键百度搜索
    // manifest.json
    {"permissions": ["contextMenus""tabs"]}
    
    // background.js
    chrome.contextMenus.create({
    	title: '使用度娘搜索:%s', // %s表示选中的文字
    	contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
    	onclick: function(params)
    	{
    		// 注意不能使用location.href,因为location是属于background的window对象
    		chrome.tabs.create({url: 'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(params.selectionText)});
    	}
    });
    
    在这里插入图片描述
  • 语法说明
    这里只是简单列举一些常用的,完整API参见:https://developer.chrome.com/extensions/contextMenus
    chrome.contextMenus.create({
    	type: 'normal'// 类型,可选:["normal", "checkbox", "radio", "separator"],默认 normal
    	title: '菜单的名字', // 显示的文字,除非为“separator”类型否则此参数必需,如果类型为“selection”,可以使用%s显示选定的文本
    	contexts: ['page'], // 上下文环境,可选:["all", "page", "frame", "selection", "link", "editable", "image", "video", "audio"],默认page
    	onclick: function(){}, // 单击时触发的方法
    	parentId: 1, // 右键菜单项的父菜单项ID。指定父菜单项将会使此菜单项成为父菜单项的子菜单
    	documentUrlPatterns: 'https://*.baidu.com/*' // 只在某些页面显示此右键菜单
    });
    // 删除某一个菜单项
    chrome.contextMenus.remove(menuItemId)// 删除所有自定义右键菜单
    chrome.contextMenus.removeAll();
    // 更新某一个菜单项
    chrome.contextMenus.update(menuItemId, updateProperties);
    

override(覆盖特定页面)

  • 使用override页可以将Chrome默认的一些特定页面替换掉,改为使用扩展提供的页面。
  • 扩展可以替代如下页面:

    历史记录:从工具菜单上点击历史记录时访问的页面,或者从地址栏直接输入 chrome://history
    新标签页:当创建新标签的时候访问的页面,或者从地址栏直接输入 chrome://newtab
    书签:浏览器的书签,或者直接输入 chrome://bookmarks

  • 注意:

    一个扩展只能替代一个页面;
    不能替代隐身窗口的新标签页;
    网页必须设置title,否则用户可能会看到网页的URL,造成困扰;

  • 替换新标签页示例:在这里插入图片描述
  • 代码(注意,一个插件只能替代一个默认页,以下仅为演示):
    "chrome_url_overrides":
    {
    	"newtab": "newtab.html",
    	"history": "history.html",
    	"bookmarks": "bookmarks.html"
    }
    

option(插件选项界面)

  • 所谓options页,就是插件的设置页面,有2个入口,一个是右键图标有一个“选项”菜单,还有一个在插件管理页面:在这里插入图片描述
  • 配置:
    {
    	"options_ui":
    	{
        	"page": "options.html",
    		// 添加一些默认的样式,推荐使用
        	"chrome_style": true
    	},
    }
    
  • 用于自定义插件配置界面:在这里插入图片描述
  • chrome41版本之前是在新标签页里启动,现在的弹窗界面好看多了
  • 注意:

    新版options中不能使用alert;
    数据存储建议用chrome.storage,因为会随用户自动同步;

桌面通知

  • Chrome提供了一个chrome.notificationsAPI以便插件推送桌面通知,暂未找到chrome.notifications和HTML5自带的Notification的显著区别及优势。
  • 在后台JS中,无论是使用chrome.notifications还是Notification都不需要申请权限(HTML5方式需要申请权限),直接使用即可。
  • 最简单的通知:在这里插入图片描述
  • 代码:
    chrome.notifications.create(null, {
    	type: 'basic',
    	iconUrl: 'img/icon.png',
    	title: '这是标题',
    	message: '您刚才点击了自定义右键菜单!'
    });
    
  • 通知的样式可以很丰富:在这里插入图片描述

devtools(开发者工具)

暂时用不上,回头补上

omnibox(搜索栏关键词触发)

暂时用不上,回头补上

总结

有丶意思

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值