Chrome扩展开发笔记

Chrome Extension

又到招聘季了(其实秋招已经过了…)。今年我们组照例没有意外的分到了0个秋招的实习生(其实分到了一个,结果第一天分给我,第二天这位同学就说不来了)。没办法,只能自己散招了。

根据往年经验,Boss直聘上面的简历质量和数量相对要靠谱一些,因此我掏钱投放了一个前端可视化方向的职位。但是每天推荐过来的人员比较多,绝大部分都是不符合我需求的,要是我一个个手动点击看过去,太花时间了。因此我自己写了一段JS,可以自动筛选符合条件的简历,高亮标注出来。

不过每次手动复制这段JS,打开控制台,再扔进去,也是比较麻烦的,因此我想,是不是可以将其做成一个Chrome扩展呢,这样每次点开Boss直聘网站,就可以自动触发JS开始进行筛选工作了。

想到就开始做吧!

原理

网站找到一篇非常不错的关于Chrome扩展的教程,里面将配置、实现都进行了清晰的讲解,因此直接看这个文章即可。

实现

这里只列出我用到的几个功能点,基础的功能实现就不罗列了,参考上面的文章即可。

数据通信

我们经常会遇到一个场景:用户通过popup页面设置一些自定义的条件,然后这些条件要被应用到inject.js中。

而popup页面是不能直接和inject.js通信的,这个时候,就必须借助content-script.js进行中转通信。

本地文件的读写,必须要一个可以支持跨域的存储接口才行。常规的localStorage是和域名绑定的,因此不能用。

可用的是chrome.storage

1
2
3
4
5
6
7
8
// 读取数据,第一个参数是指定要读取的key以及设置默认值
chrome.storage.sync.get({color: 'red', age: 18}, function(items) {
console.log(items.color, items.age);
});
// 保存数据
chrome.storage.sync.set({color: 'blue'}, function() {
console.log('保存成功!');
});

因此整体数据流程如下:

1、popup.js写入chrome.storage:

1
2
3
4
5
6
7
8
try {
let msg = 'Hello , I am test message';
chrome.storage.sync.set({testMessage: msg}, function () {
console.log('保存消息成功')
})
} catch(e) {
alert(e.message)
}

2、content-script.js读取数据,并通过window.postMessage发送消息:

1
2
3
4
chrome.storage.sync.get({testMessage: '没取到数据,这是默认的数据'}, function(items) {
console.log(`这是取自chrome.storage的数据:${items.testMessage}`);
window.postMessage({testMessage: items.testMessage}, '*')
});

3、inject.js通过window.addEventListener接收消息:

1
2
3
window.addEventListener('message', function (e) {
console.log("inject.js中,来自chrome.storage的消息:", e.data)
}, false)

版本更新

//TODO

桌面通知

可以通过chrome.notifications这个API实现,也可以通过HTML5自带的Notification实现。

考虑到便利性,我是直接采用了HTML5的Notification,这样一旦筛选到合适的人员,就可以马上发出通知。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 弹窗展示通知信息
* @param {*} msg
*/
function notify(msg) {
if (!window.Notification) {
alert('您的浏览器不支持通知功能,建议换为高版本的Chrome浏览器')
return false;
}
//如果支持window.Notification 并且 许可不是拒绝状态
if (Notification.permission === "denied") {
alert('请开启浏览器的允许通知的选项')
return false;
}

//Notification.requestPermission这是一个静态方法,作用就是让浏览器出现是否允许通知的提示
Notification.requestPermission(function (status) {
//如果状态是同意
if (status === "granted") {
var m = new Notification('来自Boss直聘的新消息', {
body: msg, //消息体内容
icon: "img/icon.png" //消息图片
});
m.onclick = function () { //点击当前消息提示框后,跳转到当前页面
window.focus();
}
} else {
log(`当前浏览器不支持弹出消息.`, MSG_TYPE.WARNING);
}
});
}

注意事项

重新加载插件

当开发完一个新功能点后,建议删除Chrome插件,重新再加载一次。

因为有时候你的代码或者配置有误,但是因为没有重新添加,是不会暴露出来的。

比如我就遇到matches这个配置项被我配错了,没有生效,但是又没有报错;直到我后来重新添加扩展,才显示了报错信息。

如果你修改了本地manifest.json,发现改动后的配置没有生效,往往就是这个配置文件有错误。

js需要以外部文件的方式引入,否则是不会执行的:

1
<script type="text/javascript" src="js/popup.js"></script>

不要刷新太快

Boss直聘有反爬机制,因此如果你刷新太快,且都是以一个相同的间隔刷新,那么就会被判断为爬虫,进而账号被永久封掉。

因此筛选数据的时候,一定要做下处理,比如每次刷新的间隔随机生成,且拉长一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 为了避免被Boss封掉账号,这里打乱时间,模拟真人操作
*/
function randomExecute() {
// 最少延迟3秒,最多13秒
let delay = Math.random() * 10000 + 3000;
// 这是执行具体筛选工作的函数
filter();


let $recommendedEl = getElementOfRecommendation();
if (!$recommendedEl) {
console.log('页面还没加载完,请稍等');
} else if ('没有更多了' === $recommendedEl.find('.loadmore').find('span').eq(0).html()) {
return;
}

// 在页面上显示距离下一次刷新的倒计时
countdown(delay)
setTimeout(randomExecute, delay);
}