自己运营了一个公众号,在发文章的时候,需要在网上找一些图,而有些网站的图片可能隐藏在属性或者背景图中,要下载的时候经常审查元素,查看源码,不太方便,最近在看一些谷歌插件的api,便顺手做了一个插件Image downloader。源码放到了github上,顺便学习并用了一下git。地址:https://github.com/yeyuqiudeng/imageDownloader

功能

Image downloader有下面几个功能:

  • 收集所有的img标签src的图片链接
  • 收集所有的背景图片链接
  • 可以根据定义的规则,收集标签属性中的链接
  • 支持图片大小筛选
  • 显示图片的原始大小

预览

manifest.json

插件用到谷歌插件中的content script和popup。content script是注入到页面中的js,需要在manifest.json配置注入页面的规则,和注入那些js进入页面。在这个插件中,我的manifest.json是这样的:

  1. {
  2. "manifest_version": 2,
  3. "name": "Image downloader",
  4. "description": "图片下载器,可以自定义属性下载规则",
  5. "version": "1.0",
  6. "browser_action": {
  7. "default_icon": "icon16.png",
  8. "default_popup": "/popup/popup.html"
  9. },
  10. "permissions": [
  11. "tabs",
  12. "downloads"
  13. ],
  14. "icons": {
  15. "16": "icon16.png",
  16. "48": "icon48.png",
  17. "128": "icon128.png"
  18. },
  19. "content_scripts": [{
  20. "matches": ["http://*/*", "https://*/*"],
  21. "js": ["common.js", "inject.js"]
  22. }]
  23. }

content_scripts的配置表示要将common.js和inject.js注入到所有http和https的网站

common公共方法

在common里我定义了两个方法,一个用来显示错误信息,一个方法将图片的相对路径补全,在cdn地址前面加上http。

方法如下:

  1. // 显示错误信息
  2. const showMsg = (msg) => {
  3. let myDate = new Date();
  4. let now = myDate.toLocaleString();
  5. console.log(now + "【" + msg + "】");
  6. };
  7. // 拼接相对路径及cdn
  8. const concatUrl = (url, domain) => {
  9. let fullPath = url
  10. if (/^\/[^\/]+/.test(url)) { // 是否为相对路径
  11. fullPath = domain + url
  12. }
  13. if (/^\/\//.test(url)) { // 是否为cdn
  14. fullPath = 'http:' + url
  15. }
  16. return fullPath
  17. }

不太熟悉正则,也不知道写得对不对。

其实这里不需要再要一个common.js的文件,只是上一次写插件的时候,公共的方法比较多,这次也将common.js留了下来。

content script

在注入页面的JS中,主要是三个方法,分别用来收集img标签的src地址,元素的背景图片和自定义属性规则的属性值

收集img标签的src值代码如下:

  1. const getImgUrl = function() { // 获取所有图片的src值
  2. const allImg = document.querySelectorAll('img')
  3. const allImgUrl = []
  4. allImg.forEach((img) => {
  5. allImgUrl.push(concatUrl(img.src, domain))
  6. })
  7. return allImgUrl
  8. }

其实就是获取img标签的集合,遍历集合并获取src的值,如果为相对路径或cdn路径,用concatUrl方法拼接成绝对路径,最后组成一个由url地址组成的数组。

获取背景图片的代码如下:

  1. const getBackgroundImage = function() { // 获取背景图片
  2. const allDoms = document.querySelectorAll('*')
  3. const allBgImageUrl = []
  4. allDoms.forEach((element) => {
  5. let url = window.getComputedStyle(element)['background-image'].match(/url\("(.+)"\)$/)
  6. if (url && url[1]) {
  7. allBgImageUrl.push(concatUrl(url[1], domain))
  8. }
  9. })
  10. return allBgImageUrl
  11. }

通过getComputedStyle方法来获取所有元素的backgroundImage属性值,并将url地址提取出来,如果一个backgroundImage中有多个url,只取第一个,后面的就舍弃了。这个方法也是返回一个由地址组成的数组。

获取配置属性值的代码如下:

  1. let configAttr = ['data-src'] // 配置的属性
  2. const getConfigAttrUrl = function() { // 获取所有配置属性的值
  3. const attrUrl = []
  4. if (configAttr.length > 0) {
  5. configAttr.forEach((attr) => {
  6. attrUrl.push(...getAllAttr(attr))
  7. })
  8. }
  9. return attrUrl
  10. }
  11. const getAllAttr = function(attr) { // 获取对应属性的值
  12. const attrs = []
  13. const allDoms = document.querySelectorAll('[' + attr + ']')
  14. allDoms.forEach((dom) => {
  15. const attrValue = dom.getAttribute(attr)
  16. attrs.push(concatUrl(attrValue, domain))
  17. })
  18. return attrs
  19. }

configAttr用来配置需要获取元素属性的规则,这里用了数组来接收多个配置规则,默认收集所有元素的data-src属性值。为什么会内置这个规则呢?因为很多网站都用了这个属性啊。

getAllAttr是根据传进来的属性获取属性值,getConfigAttrUrl是遍历属性规则,收集所有属性规则下的所有属性值,返回一个属性值数组。

图片不会在进入页面后马上就进行收集,只会在用户点击插件时才开始收集当前页面的图片,并将收集到的数据发送给popup处理。content script怎样与popup交互,下一篇文章再说。

最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:

谷歌插件Image downloader开发之 content script的更多相关文章

  1. 谷歌插件Image downloader开发之popup

    Image downloader的交互逻辑是这样的:用户点击Image downloader的图标,会向页面(content script,见上一篇文章:谷歌插件Image downloader开发之 ...

  2. Vim下的Web开发之html,CSS,javascript插件

    Vim下的Web开发之html,CSS,javascript插件   HTML 下载HTML.zip 解压HTML.zip,然后将里面的所有文件copy到C:\Program Files\Vim\vi ...

  3. 插件开发之360 DroidPlugin源码分析(五)Service预注册占坑

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52264977 在了解系统的activity,service,broa ...

  4. 插件开发之360 DroidPlugin源码分析(四)Activity预注册占坑

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52258434 在了解系统的activity,service,broa ...

  5. Android插件化开发之OpenAtlas生成插件信息列表

    上一篇文章.[Android插件化开发之Atlas初体验]( http://blog.csdn.net/sbsujjbcy/article/details/47446733),简单的介绍了使用Atla ...

  6. Android混合开发之WebViewJavascriptBridge实现JS与java安全交互

    前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...

  7. Android混合开发之WebView与Javascript交互

    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...

  8. Liferay7 BPM门户开发之37: Liferay7下的OSGi Hook集成开发

    hook开发是Liferay客制扩展的一种方式,比插件灵活,即可以扩展liferay门户,也能对原有特性进行更改,Liferay有许多内置的服务,比如用hook甚至可以覆盖Liferay服务. 可作为 ...

  9. C# WinForm 技巧八:界面开发之“WeifenLuo.WinFormsUI.Docking+OutLookBar” 使用

    概述      最近几天一直在关注WinFrom方面的文章主要还是园子里伍华聪的博客,在看看我们自己写的项目差不忍赌啊,有想着提炼一下项目的公共部分,公共部分有分为 界面,类库两方面,今天主要是把界面 ...

随机推荐

  1. halcon读取一张照片,并转化为灰度图像

    dev_close_window () read_image (Image, 'E:/图片/123.jpg') get_image_size (Image, Width, Height) dev_op ...

  2. poj 1286&&poj2409 Polya计数 颜色匹配

    #include <iostream> #include <math.h> using namespace std; #define LL long long LL gcd(L ...

  3. Java 对象内存占用

    java基本类型及对象占用的内存大小 请参考下面文章 原始类型及对象占用的内存大小 http://www.javamex.com/tutorials/memory/object_memory_usag ...

  4. 记AbpSession扩展实现过程

    AbpSession只给了userId和TenantId,这次实际项目中并不够用,网上找了很久也没找到好的实现方法.项目初期没有时间进行研究,最近空了试了一下,大致实现添加额外字段并读取相应值的功能. ...

  5. PDO vs. MySQLi 选择哪一个?(PDO vs. MySQLi: Which Should You Use?)-转载

    用Php访问数据的时候,你选择MySQLi和PDO,在选择之前,你应该知道些什么呢? 这篇文章将会介绍这两种方式的不同点,数据库的支持.稳定性.性能等问题. 概述   PDO MySQLi Datab ...

  6. Sql Server tempdb原理-缓存机制解析实践

    Tempdb就像Sqlserver的临时仓库,各式各样的对象,数据在里面进行频繁计算,操作.大量的操作使得tempdb可能面临很大压力,tempdb中缓存的设计就是为了缓解这些压力.这次就为大家介绍下 ...

  7. C#中的线程四(System.Threading.Thread)

    C#中的线程四(System.Threading.Thread) 1.最简单的多线程调用 System.Threading.Thread类构造方法接受一个ThreadStart委托,改委托不带参数,无 ...

  8. WPF,Silverlight与XAML读书笔记第四十三 - 多媒体支持之文本与文档

    说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘>的编排,对内容进行了总结并加入一些个人理解. Glyphs对象(WPF,Silverlig ...

  9. C#Light 和 uLua的对比第二弹

    上次的对比大家还有印象否,C#Light和ulua对比各有胜负 今天我们加入一个去反射优化,这是uLua没办法实现的优化,我们也就只能不要脸的胜之不武了 以原生执行同一测试时间为X1,数字越小的越快 ...

  10. [ACM_动态规划] Alignment (将军排队)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28415#problem/F 题目大意:有n个士兵排成一列,将军想从中抽出最少人数使队伍中 ...