当前位置: 首页 > 科技观察

30分钟开发一款抓取网站图片资源的浏览器插件

时间:2023-03-11 21:13:29 科技观察

30分钟开发一个抓取网站图片资源的浏览器插件浏览器插件,所以我也花了大约一天的时间阅读了谷歌浏览器插件开发文档,这里特总结一下经验,和一个实际案例来回顾插件开发过程和注意事项。您将学习如何快速开始浏览器插件开发。浏览器插件开发的核心概念。浏览器插件的通信机制。浏览器插件的数据存储。浏览器插件的应用场景。开发一个抓取网站图片资源的浏览器插件。正文开始前,先看一下作者总结的概览:如果你熟悉浏览器插件开发,可以直接看上一节插件开发实战。1.入门首先,我们来看一下浏览器插件的定义:浏览器插件是一种基于网络技术(如HTML、JavaScript和CSS)构建的可以自定义浏览体验的小型软件程序。它们允许用户根据个人需要或偏好自定义Chrome的功能和行为。开发一个浏览器插件,我们只需要有一个manifest.json文件即可。为了快速开发一个浏览器插件,我们需要打开浏览器开发者工具。具体步骤如下:在谷歌浏览器中输入chrome://extensions/。启用开发者模式。导入您自己的浏览器插件包。通过以上三步,我们就可以开始浏览器插件的开发之旅了。浏览器插件一般都放在浏览器地址栏的右侧。我们可以在manifest.json文件中配置插件的图标,并配置一定的规则。看我们的浏览器插件图标,如下图所示:下面详细讲解一下浏览器插件开发的核心概念。2、核心知识点浏览器插件一般涉及以下核心文件:manifest.json用于配置所有插件相关的配置(必须放在根目录下)。background.js后台脚本(后台页面),生命周期与浏览器一致,一般放置全局代码。内容脚本插件是一种将脚本注入页面的形式。我们可以通过content-scripts向页面注入js和css资源,并控制允许注入的范围。popup是点击插件图标后打开的自定义窗口,用于处理用户交互。笔者画了一张简单的图,大致展示了它们之间的关系:接下来,我们来详细了解一下以上核心知识点。(1)manifest.json谷歌官网为我们提供了一个简单的配置,如下:{"name":"MyExtension","version":"2.1","description":"GetsinformationfromGoogle.","图标”:{“128”:“icon_16.png”,“128”:“icon_32.png”,“128”:“icon_48.png”,“128”:“icon_128.png”},“背景”:{“持久”:假,“脚本”:[“background_script.js”]},“权限”:[“https://*.google.com/”,“activeTab”],“browser_action”:{“default_icon”:"icon_16.png","default_popup":"popup.html"}}各字段含义介绍如下:name浏览器插件名称,会显示在插件列表中。description浏览器插件简介,方便告诉开发者该插件的功能和功能,会显示在插件列表中。版本浏览器插件版本。icon浏览器插件图标。后台后台页面的脚本路径一般是插件目录的相对地址。Permissions允许使用浏览器API权限,如contextMenus(右键菜单)、tabs(操作标签)、webRequest(使用web请求)、storage(允许使用本地存储)、"http://*"(可以通过executeScript或insertCSS访问)。browser_action浏览器右上角的图标设置(包括弹出页面、鼠标悬停时的标题、图标等)。content_scripts需要直接注入到页面的javascript脚本中。web_accessible_resources是普通页面可以直接访问的插件资源列表。如果不设置,则不能直接访问。chrome_url_overrides覆盖浏览器的默认页面(通常用作浏览器的自定义桌面)。omn??ibox通过地址栏注册一个关键字来提供搜索建议,并且只能设置一个关键字(多用于自定义搜索屏蔽)。default_locale默认语言(如“zh_CN”)。(2)background.js后台页面主要用来提供一些全局配置,事件监听,业务转发等。几个常见的情况:定义右键菜单。//background.jsconstsystems={a:'有趣的前端',b:'掘金',c:'微信'}chrome.runtime.onInstalled.addListener(function(){//contextmenufor(letkeyofObject.keys(systems)){chrome.contextMenus.create({id:key,title:systems[key],type:'normal',contexts:['selection'],});}});//清单.json{"permissions":["contextMenus"]}有以下作用:只有带有.com后缀的页面才会激活插件。chrome.runtime.onInstalled.addListener(function(){//类似于浏览器插件图标激活时:[newchrome.declarativeContent.PageStateMatcher({pageUrl:{hostSuffix:'.com'},})],actions:[newchrome.declarativeContent.ShowPageAction()]}]);});});如下图所示,当页面地址的后缀不等于.com时,插件图标将不会被激活:与content_script或弹出页面的消息通信。chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){console.log(sender.tab?"来自内容脚本:"+sender.tab.url:"来自扩展");if(request.greeting=="hello")sendResponse({farewell:"goodbye"});});(3)content-scriptscontentscripts一般植入到页面中,可以控制页面中的dom。我们可以用它来屏蔽网页广告,自定义页面皮肤等。manifest.json中的基本配置如下:{"content_scripts":[{"matches":["http://*/*","https://*/*"],"js":["lib/jquery3.4.min.js","content_script.js"],"css":["base.css"]}],}中上面的代码我们定义指定content_scripts允许注入的页面范围,插入页面的js和css,这样我们就可以很方便的改变某个页面的样式。比如我们可以在页面中注入一个按钮:content_scripts我会在后面的浏览器插件案例中详细介绍。(4)popuppopup是用户点击插件图标时打开的小窗口。当失去焦点时,窗口立即关闭。我们一般用它来处理一些简单的用户交互和插件指令。由于弹窗也是一个网页,所以我们一般会创建一个popup.html和popup.js来控制弹窗的显示和交互。我们在manifest.json中配置如下:{"page_action":{"default_title":"小溪图片提取插件","default_popup":"popup.html"},}这里需要注意一点,我们不能直接使用popup.html中的script脚本,我们需要导入脚本文件。如下:在线图片提取工具<正文>

下面是作者写的一个插件的弹窗页面:3.通信机制对于一个比较复杂的浏览器插件,我们不仅需要操作dom或者提供基本的功能,我们还需要从第三方或您自己的服务器上获取有用的页面数据。这时候就需要用到插件的通信机制了。因为当前页面存在content_script脚本,受同源策略影响,所以我们无法抓取抓取的数据。传递给第三方平台或者自己的服务器,所以我们需要一个基于浏览器的通信API。以下是谷歌浏览器插件的通信过程:(1)弹窗与后台通信。从官方文档我们知道弹窗是可以直接访问后台页面的,因此弹出窗口可以直接与其通信://background.jsvargetData=(data)=>{console.log('getData:'+data)}//popup.jsletbgObj=chrome.extension.getBackgroundPage();bgObj.getData();//访问bg函数复制代码3.2Popup或后台页面与content_script通信这里我们使用chrometabsAPI,如下://popup.js//向content_script发送消息chrome.tabs.query({active:true,currentWindow:true},function(tabs){chrome.tabs.sendMessage(tabs[0].id,"activeBtn",function(response){console.log(response);});});//接收消息chrome.runtime.onMessage.addListener(function(request,sender,sendResponse){console.log(sender.tab?"fromacontentscript:"+sender.tab.url:"fromtheextension");if(request.greeting=="你好")sendResponse({告别:"再见"});});content_script接收和发送消息://接收消息chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){if(message=="activeBtn"){//...sendResponse({告别:"激活成功"});}});//主动发送消息chrome.runtime.sendMessage({greeting:"hello"},function(response){console.log(response,document.body);//document.body.style.backgroundColor="orange"});复制代码消息的长连接在谷歌官网上也写的很清楚:我们可以使用下面的方法建立长连接://content_script.jsvarport=chrome.runtime.connect({name:"徐晓曦"});port.postMessage({Ling:"Hello"});port.onMessage.addListener(function(msg){if(msg.question=="Whatareyoudoing?")port.postMessage({answer:"Movebricks"});elseif(msg.question=="搬砖有钱吗?")port.postMessage({answer:"没有"});});//popup.jschrome.runtime.onConnect.addListener(function(port){port.onMessage.addListener(function(msg){if(msg.Ling=="Hello")port.postMessage({question:"你在做什么?"});elseif(msg.answer=="搬砖")port.postMessage({question:"搬砖有钱吗?"});elseif(msg.answer=="No")port.postMessage({question:"太难了...orbackground),我们可以在上面三个页面获取,具体用法如下:chrome.storage.sync.get('imgArr',function(data){console.log(data)});//save数据chrome.storage.sync.set({'imgArr':imgArr},function(){console.log('保存成功');});//另一种方式chrome.storage.local.set({key:value},function(){console.log('Valueissetto'+value);});5.应用场景插件在谷歌浏览器中的应用场景有很多,如文章开头的思维导图所写。以下是笔者的总结如果你对一些应用场景感兴趣,可以尝试实现:谷歌浏览器自定义桌面网页性能分析工具。网络爬虫。埋地工具。为网页生成热图的工具。安全拦截插件。广告过滤插件。网站动态换肤。第三方数据导入。代码格式化工具。在线协作工具。反作弊插件。还有很多实用的工具可以开发,大家可以把玩。下面通过实现一个网页图片提取插件来总结一下下面的浏览器插件开发过程。6.开发一个抓取网站图片资源的浏览器插件,首先按照作者的风格,开发任何工具之前都必须明确需求,那么我们先来看看插件的功能点:它可以嵌入网页按钮,只需单击一个按钮即可捕获网页图像。可以在客户端显示捕获的图片。单击插件可预览捕获的图片。基本上就是这些功能,接下来我会展示核心代码。在介绍代码之前,先预览一下插件的实现效果:插件目录结构如下:由于插件开发比较简单,我直接使用jquery开发。这里主要关注popup.js和content_script.js。popup.js主要用于获取content_script页面传来的图片数据,并显示在popup.html中。另外需要注意的是,当页面没有注入生成按钮时,popupu需要向内容页面发送信息,主动让其生成按钮。代码如下:chrome.storage.sync.get('imgArr',function(data){data.imgArr&&data.imgArr.forEach(item=>{varimgWrap=$("
")varimg=$("")imgWrap.append(img);$('#content').append(imgWrap);$('.empty').hide();})});$('#activeBtn').click(function(element){chrome.tabs.query({active:true,currentWindow:true},function(tabs){chrome.tabs.sendMessage(tabs[0].id,"activeBtn",function(response){console.log(response);});});});对于内容页面,我们需要实现的是动态生成按钮,并在页面中植入弹窗,展示获取到的图片。另一方面,我们需要将图片数据传入storage,这样弹出页面才能获取到图片数据。由于页面比较简单,我不需要太多的第三方库。我只是简单地手写一个模态组件。代码如下://popup~functionModal(){varmodal;if(thisinstanceofModal){this.init=function(opt){modal=$("
");vartitle=$(""+opt.title+"
");varclose_btn=$("X");varcontent=$("");varmask=$("");close_btn.click(function(){modal.hide()})title.append(close_btn);内容追加(标题);content.append(opt.content);模态追加(内容);模态追加(掩码);$('正文').append(模态);}this.show=function(opt){if(modal){modal.show();}else{varoptions={title:opt.title||'标题',内容:opt.content||''}this.init(options)模式l.show();}}this.hide=function(){modal.hide();}}else{window.Modal=newModal()}}()第一步是批量获取页面图片数据:varimgArr=[]$('img').each(function(i){varsrc=$(this).attr('src');varrealSrc=/^(http|https)/.test(src)?src:location.protocol+'//'+location.host+src;imgArr.push(realSrc)})因为图片的src路径可能是相对地址,所以笔者这里使用正则表达式来简单处理以下,当然我们可以进行细粒度的控制更改第二步将图片数据存入storage:chrome.storage.sync.set({'imgArr':imgArr},function(){console.log('savedsuccessful');});第三步,生成预览图片的弹窗,这里是作者上面实现的modal组件:Modal.show({title:'extractionresult',content:imgBox})第四步,当popup发送激活按钮的通知,我们需要在网页中显示动态插入生成的按钮:chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){if(message=="activeBtn"){if(!$('.crawl-btn')){$('body').append("extract")}else{$('.crawl-btn').css("background-color","orange");setTimeout(()=>{$('.crawl-btn').css("background-color","#06c");},3000);}sendResponse({告别:"激活成功"});}});setTimeout纯粹是为了引起用户的注意,当然我们可以用更优雅的方式来处理。插件的核心代码主要就是这些。当然,还有很多细节需要考虑。我把配置文件和一些细节放在了github上。有兴趣的可以安装体验一下。github地址:https://github.com/MrXujiang。本文转载自微信公众号“趣话前端”,可通过以下二维码关注。转载本文请联系前端公众号。