前言
当我查询百度时,部分网站提供的答案并不准确或者并无参考价值,那么此时便想直接过滤掉这一部分搜索结果,虽然在谷歌插件市场已有很多类似产品,但是最近我刚好在学习谷歌插件,那么决定自己做一款。
准备工作
- 编辑器 谷歌插件并不需要特定的编辑器,最普通的记事本亦可编写。本人用的是VSCode。
- icon 谷歌插件需要四张不同尺寸的icon图片,尺寸分别为1616、3232、4848、128128。
- 谷歌账号 如果需要上架,那么需要一个google账号。
- 其它 谷歌插件可以引入js插件,例如jquery等。根据习惯来。
开始写写写了
1 创建基本的文件结构
文件结构说明:
images文件夹-放置icon图片,其中source为原图,.keep文件为git生成的文件;
background.js-相当于插件初始js文件;
constan.js-此文件为作者新增的js文件,放置content所需要用到的变量值和常量值;
content.js-与页面交互的js文件,可以修改页面的所有内容,包括标签,样式等等;
manifest.json-插件配置文件,扩展程序中首先读取的就是该文件;
options.css、options.html、options.js-插件选项界面,右键插件图标,点击选项。
popup.css、popup.html、popup.js-插件的操作界面,左键点击插件图标。
2 修改配置文件-manifest.json
申请权限说明:
storage-插件缓存;
tabs-获取当前打开的所有tab页;
3 编写background.js
// 插件内部消息类型
const MESSAGE_TYPE = {
UPDATE_EXCLUDE_SITE: 1
};
// 排除网站列表-可以设置默认需要排除的网站
const EXCLUDE_SITE_LSIT = [];
// 将以上变量放入缓存
chrome.storage.sync.set({
messageType: MESSAGE_TYPE,
excludeSiteList: EXCLUDE_SITE_LSIT
});
4 分析百度搜索结果页
在这里,我们可以清楚的看到每一个搜索结果都是一个div,其中attr为mu的为链接地址,然后每一个div的class为result c-container xpath-log new-pmd,那么我就可以查找所有class=‘result c-container xpath-log new-pmd’的div标签,然后获取mu属性的值,判断是否在需要排除的网站列表中,如果在,试用remove将其移除即可。
5 编写content.js 在编写过程中,发现class=‘result c-container xpath-log new-pmd’的标签和现实的内容条数不对等,因此更换获取方式,后来发现所有的div均在一个id=content_left的div下,因此查找id=content_left的div下所有第一层级的div,然后获取mu,判断是否在需要排除的网站列表中。
$(function (){
// 获取初始化信息
chrome.storage.sync.get(['messageType', 'excludeSiteList']).then((result) => {
MESSAGE_TYPE = result.messageType;
EXCLUDE_SITE_LSIT = result.excludeSiteList;
});
// 排除网站搜索结构-采用倒序排除
function excludeSite(){
for(var i = $("#content_left>div").length - 1;i >= 0;i --){
let mu = $("#content_left>div").eq(i).attr("mu");
if(mu != undefined){
mu = mu.substr(mu.indexOf("//") + 2);
mu = mu.substr(0, mu.indexOf("/"));
if($.inArray(mu, EXCLUDE_SITE_LSIT) !== -1){
$("#content_left>div").eq(i).remove();
}
}
}
}
// 等待内容显示时,才进行排除操作
let waitConShow = setInterval(function (){
let content = $("#content_left");
if(content != undefined && content){
clearInterval(waitConShow);
excludeSite();
}
}, 500);
})
6 编写完background.js后即可开始测试,打开谷歌浏览器,打开扩展程序界面,打开开发者模式,加载已解压的文件夹。
7 问题以及深思
测试后,发现第一次搜索时可以做到排除,但是后续的搜索无法排除,这里是因为content.js是跟着页面刷新而刷新的,后续的搜索结果是无页面刷新重载结果的形式,因此不会重新触发,这里的解决方案有以下两种:
一、setInterval来定时排除
二、当用户点击搜索按钮或者监控用户的回车按钮点击事件-推荐此种方式
除了上述问题,还有一个问题,那么就是如果我要修改排除的网站列表呢,总不能每次去文件修改,然后刷新插件,再使用吧。因此需要一个操作界面,这个操作界面可以使插件的操作界面,也可以直接在页面中增加一块固定区域,这个操作界面用来设置需要排除的界面。
8 问题解决
- setInterval定时调用排除方法-修改部分代码
$(function (){
// 获取初始化信息
chrome.storage.sync.get(['messageType', 'excludeSiteList']).then((result) => {
MESSAGE_TYPE = result.messageType;
EXCLUDE_SITE_LSIT = result.excludeSiteList;
});
// 排除网站搜索结构-采用倒序排除
function excludeSite(){
for(var i = $("#content_left>div").length - 1;i >= 0;i --){
let mu = $("#content_left>div").eq(i).attr("mu");
if(mu != undefined){
mu = mu.substr(mu.indexOf("//") + 2);
mu = mu.substr(0, mu.indexOf("/"));
if($.inArray(mu, EXCLUDE_SITE_LSIT) !== -1){
$("#content_left>div").eq(i).remove();
}
}
}
}
// 等待内容显示时,才进行排除操作
let waitConShow = setInterval(function (){
let content = $("#content_left");
if(content != undefined && content){
clearInterval(waitConShow);
excludeSite();
setInterval(function (){
excludeSite();
}, 1000);
}
}, 500);
})
- 监听搜索按钮点击事件和回车按钮点击事件
$(function (){
// 获取初始化信息
chrome.storage.sync.get(['messageType', 'excludeSiteList']).then((result) => {
MESSAGE_TYPE = result.messageType;
EXCLUDE_SITE_LSIT = result.excludeSiteList;
});
// 排除网站搜索结构-采用倒序排除
function excludeSite(){
for(var i = $("#content_left>div").length - 1;i >= 0;i --){
let mu = $("#content_left>div").eq(i).attr("mu");
if(mu != undefined){
mu = mu.substr(mu.indexOf("//") + 2);
mu = mu.substr(0, mu.indexOf("/"));
if($.inArray(mu, EXCLUDE_SITE_LSIT) !== -1){
$("#content_left>div").eq(i).remove();
}
}
}
}
// 等待内容显示时,才进行排除操作
function main(){
let waitConShow = setInterval(function (){
let content = $("#content_left");
if(content != undefined && content){
clearInterval(waitConShow);
excludeSite();
}
}, 500);
}
// 等待内容显示时,才进行排除操作
let waitConShow = setInterval(function (){
let content = $("#content_left");
if(content != undefined && content){
clearInterval(waitConShow);
excludeSite();
$("#su").click(function (){
main();
});
$(document).keyup(function(e) {
if (e.keyCode === 13) {
main();
}
});
}
}, 500);
})
- 页面增加操作界面-content.js文件直接增加
此种方法编写过程中出现div标签无法显示的问题,通过查看F12的console,看到如下描述,大概意思应该是为了安全给我的标签删除,因此作者放弃本方案,采用第二方案。
- 插件弹出页面增加操作界面-popup.html、popup.js、popup.css popup.html
<!-- 弹出框界面 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="popup.css">
</head>
<body>
<div id="fl-option">
<div id="fl-option-add">
<input id="fl-otion-add-con" type="text" placeholder="网站host" />
<button id="fl-option-add-button" >增加</button>
</div>
<div id="fl-option-list">
</div>
<div id="fl-option-add">
<button id="fl-option-del-button">移除选中</button>
</div>
</div>
<!-- import jquery script -->
<script type="text/javascript" charset="utf-8" src='jquery-3.7.1.min.js'></script>
<!-- import selfDefined script -->
<script type="text/javascript" charset="utf-8" src='popup.js'></script>
</body>
</html>
popup.js
$(function (){
// defined constant
let MESSAGE_TYPE;
let EXCLUDE_SITE_LSIT = [];
// init enum
chrome.storage.sync.get(['messageType', 'excludeSiteList']).then((result) => {
MESSAGE_TYPE = result.messageType;
EXCLUDE_SITE_LSIT = result.excludeSiteList;
refreshSiteListPage();
document.getElementById("fl-option-add-button").addEventListener("click", optionAdd);
document.getElementById("fl-option-del-button").addEventListener("click", optionDel);
});
async function syncPage(){
chrome.storage.sync.set({
excludeSiteList: EXCLUDE_SITE_LSIT
});
chrome.tabs.query({ active: true,currentWindow: true}, function(tabs) {
if (tabs.length > 0) {
let activeTab = tabs[0];
(async () => {
await chrome.tabs.sendMessage(activeTab.id, getMessage(MESSAGE_TYPE.UPDATE_EXCLUDE_SITE, null));
})();
}
});
}
// 添加需要排除的网页
function optionAdd(){
EXCLUDE_SITE_LSIT.push($("#fl-otion-add-con").val());
$("#fl-otion-add-con").val("");
refreshSiteListPage();
syncPage();
}
// 删除需要排除的网页
function optionDel(){
EXCLUDE_SITE_LSIT = [];
for(var i = 0;i < $("#fl-option-list").find("input:checkbox").length;i ++){
if($("#fl-option-list").find("input:checkbox").eq(i).prop('checked') == false){
EXCLUDE_SITE_LSIT.push($("#fl-option-list").find("input:checkbox").eq(i).val());
}
}
refreshSiteListPage();
syncPage();
}
// 刷新排除网站列表界面
function refreshSiteListPage(){
$("#fl-option-list").html("");
let htmlStr = "";
for(var i = 0;i < EXCLUDE_SITE_LSIT.length;i ++){
htmlStr += '<label><input type="checkbox" value="' + EXCLUDE_SITE_LSIT[i] + '"/>' + EXCLUDE_SITE_LSIT[i] + '</label>';
}
$("#fl-option-list").append(htmlStr);
}
// 插件内部通讯实体
function getMessage(messageType, messageData){
return {
type: messageType,
data: messageData
};
}
});
popup.css
body {
width: 200px;
height: auto;
font-size: 12px;
font-family: "微软雅黑";
}
h1 {
background-color: antiquewhite;
font-weight: 100;
}
#fl-option{
width: 200px;
height: 400px;
#fl-option-add{
display: flex;
align-items: center;
justify-content: space-between;
input{
width: 130px;
}
}
#fl-option-list{
display: flex;
flex-wrap: wrap;
align-items: center;
label{
display: flex;
align-items: center;
}
}
}
下班了下班了,先这样吧,完整代码请参考Gitee仓库。