Commit 27ce987e authored by 邱旭's avatar 邱旭

doc

parent ef313db5
# 2021年6月23日Chrome插件开发快速入门
#### 本节内容案例仅供学习,下载后请在24小时内删除
[代码地址](http://gitlab.dui88.com/haiyoucuv/qiuxu_code/tree/%E9%82%B1%E6%97%AD_%E7%99%BE%E5%BA%A6%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD%E5%99%A8_20210623)
## 本讲内容
- 1.了解Chrome插件开发
- 2.详细介绍Chrome插件manifest清单配置
- 3.注入css实战(让网页变灰)
- 4.注入JS脚本实战(注入并弹出alert提示)
- 5.分析百度广告,编写插件删除广告
## 1.如何开发一款Chrome插件
![img.png](./img/img.png)
Chrome将会把manifest.json文件作为插件的描述文件,文件夹里包含该文件将被认为是插件
## 2.详解manifest文件
```json5
{
"manifest_version": 2,
// 清单版本号
"name": "插件名称",
"version": "1.8.6",
// 版本号
"description": "描述",
"author": "作者",
"icons": {
// 图标
"16": "xxx.png",
"48": "xxx.png",
"128": "xxx.png"
},
// browser_action 和 page_action 只能添加一个
"browser_action": {
// 浏览器行为,所有页面均生效
"default_icon": "xxx.png",
// 图标的图片
"default_title": "标题",
"default_popup": "html/popup.html"
//单击图标后弹窗页面
},
"page_action": {
// 页面行为,只在特定页面下生效
"default_icon": {
"24": "xxx.png",
"38": "xxx.png"
},
"default_popup": "xxx.html",
"default_title": "页面标题"
},
"background": {
// 后台脚本,可简单理解为服务器
"scripts": [
"xxx.js",
]
},
"devtools_page": "xxx.html",
"content_scripts": [
// 注入的脚本,css等
{
"js": [
"xxx.js"
],
"css": [
"xxx.css"
],
"matches": [
"<all_urls>"
]
// 只在这些站点下生效 <all_urls> 表示全部
}
],
"permissions": [
// 所需要的权限
"cookies",
"http://*/*",
"management",
"tabs",
"contextMenus"
]
}
```
比较重要的几项有以下几项:
`content_scripts`:描述需要注入的文件,并描述在哪些网页下注入,何时注入;
`browser_action``page_action`:可以创建窗口,在窗口创建页面,browser_action是浏览器行为,page_action是页面行为,这两个只能存在一个;
`devtools_page`:可以在devtools里创建窗口,并且可以使用Chrome提供的devtools API;
`background`:可将其简单理解为服务器,可以用作通信等,如devtools和注入脚本的通信;
## `content_scripts`
```json5
{
"content_scripts": [
{
"js": [
"xxx.js"
],
"css": [
"xxx.css"
],
"run_at": "document_end",
"matches": [
"https://*.baidu.com/*"
]
}
]
}
```
| 字段名 | 含义 |
| :---: | :---: |
| js | 要注入的js文件 |
| css | 要注入的css文件 |
| run_at | 在什么时候注入<br/>document_end<br/>document_start<br/>document_idle |
| matches | 只在这些规则的URL下生效<br/><all_urls>表示在所有网站下都生效 |
## 创建一个插件
- 新建一个文件夹
在文件夹内创建style.css文件和index.js文件
在文件夹内创建manifest.json文件,内容如下:
```json
{
"manifest_version": 2,
"name": "百度广告屏蔽器",
"version": "0.0.1",
"description": "屏蔽百度广告",
"icons": {
},
"author": "你的名字",
"content_scripts": [
{
"js": [
"index.js"
],
"css": [
"style.css"
],
"run_at": "document_end",
"matches": [
"https://*.baidu.com/*"
]
}
]
}
```
- 打开Chrome -> 菜单 -> 更多工具 -> 扩展程序
![img.png](img/img1.png)
- 打开右上角开发者模式,然后将你的插件文件夹直接拖进去,就安装好了
![img.png](img/img2.png)
- 注意,每修改一次代码需要在这里刷新一次,不然Chrome不会重新加载
## 完成注入css实战,让网页变灰
在style.css中写入如下内容
```css
body {
filter: grayscale(1);
}
```
刷新重新加载插件文件,并打开 [百度](https://www.baidu.com/) 可以看到整个网页都变灰了
![img.png](img/img3.png)
## 完成注入JS脚本实战,注入并弹出alert提示
在index.js中写入如下内容
```javascript
alert("插件生效");
```
刷新网页,看到弹出提示
![img.png](img/img4.png)
## 分析百度广告,实现屏蔽功能
![img.png](img/img5.png)
随意搜索一些内容,发现在搜索页的广告都是在一个id叫`content_left`下的第一个div里
并且这个div没有id属性,而正常的搜索结果有id属性
则可以在插件中写入如下代码:
```javascript
const content_left = document.getElementById("content_left");
if (content_left && content_left.children > 0 && !content_left.children[0].id) {
content_left.children[0].remove();
}
```
达到屏蔽搜索结果广告的目的
## 动态加载的广告如何去除
随意打开百度百科的一个词条,发现右边有一些烦人的广告,和我们的搜索的结果毫无关系
![img.png](img/img6.png)
使用同样的方法去分析这两个广告 右侧图片广告为className叫`right-ad`的元素 右侧词条广告为id是`side_box_unionAd`的元素
写入代码将其移除
```javascript
// 百科右侧图片广告
const right_ad = document.getElementsByClassName("right-ad");
if (right_ad[0]) {
right_ad[0].remove();
}
// 百科右侧恶心的广告
const side_box_unionAd = document.getElementById("side_box_unionAd");
if (side_box_unionAd) {
side_box_unionAd.remove();
}
```
发现并没有效果,是因为这两个广告都是动态载入的,而我们的js脚本是在document创建结束的时候就已经执行了
对于这两种广告,我们可以监听dom变化,来完成移除
以下是两种监听dom变化的方法,
`DOMSubtreeModified`事件在DOM2中就已经提供
`MutationObserver`在DOM3中被写入浏览器标准API
```javascript
// 监听dom结构变化 DOM2
document.body.addEventListener("DOMSubtreeModified", () => {
console.log("DOMSubtreeModified");
});
// 监听dom结构变化 DOM3
const observer = new MutationObserver(() => {
console.log("MutationObserver");
});
observer.observe(document.body, {
childList: true,
// attributes: true,
subtree: true,
});
```
我们使用`MutationObserver`来监听dom树的变化
`childList``subtree`设置为`true`,表示监听子节点及其后代的结构变化
在创建`MutationObserver`时传入回调函数
在回调函数中传入移除广告的方法
重载插件并刷新百科页面,发现广告已经被移除了
```javascript
/**
* 通过监听dom树的变化,移除异步加载的的广告
*/
function removeAdAsync() {
// 百科右侧图片广告
const right_ad = document.getElementsByClassName("right-ad");
if (right_ad[0]) {
right_ad[0].remove();
}
// 百科右侧恶心的广告
const side_box_unionAd = document.getElementById("side_box_unionAd");
if (side_box_unionAd) {
side_box_unionAd.remove();
}
}
// 监听dom结构变化 DOM2
// document.body.addEventListener("DOMSubtreeModified", removeAdAsync);
// 监听dom结构变化 DOM3
const observer = new MutationObserver(removeAdAsync);
observer.observe(document.body, {
childList: true,
// attributes: true,
subtree: true,
});
```
## 新的思考
提供三个视频网站移除播放广告的方法
大家可以尝试制作相关插件
爱奇艺视频广告
```javascript
$(".skippable-after").click()
```
腾讯视频广告
```javascript
$(".txp_ad").find("txpdiv").find("video")[0].currentTime = 100;
$(".txp_ad").find("txpdiv").find("video")[1].currentTime = 100;
```
优酷视频广告
```javascript
$(".h5-ext-layer").find("div").remove();
$(".control-play-icon").click();
```
......@@ -52,3 +52,4 @@ observer.observe(document.body, {
// attributes: true,
subtree: true,
});
......@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "百度广告屏蔽器",
"version": "0.0.1",
"description": "屏蔽天杀的百度广告",
"description": "屏蔽百度广告",
"icons": {
},
"author": "haiyoucuv",
......@@ -13,13 +13,5 @@
"run_at": "document_end",
"matches":["https://*.baidu.com/*"]
}
],
"permissions": [
"cookies",
"http://*/*",
"https://*/*",
"management",
"tabs",
"contextMenus"
]
}
body{
/*background-color: black;*/
/*filter: grayscale(1);*/
}
/*body{*/
/* filter: grayscale(1);*/
/*}*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment