chrome浏览器插件开发-实践-爬取页面图片资源

功能描述

        通过插件实现一键获取当前页面的所有图片资源,将所有图片展示到插件界面,方便查看和下载图片。

开发思路和方案

        html的图片资源有两种,一种是img标签,另一种是页面元素的背景图片。插入到页面的内容脚本可以访问document,通过document.getElementsByTagName('img')获取所有img标签,拿到所有img图片的地址;通过document.querySelectorAll('*')获取所有元素,然后使用window.getComputedStyle方法获取节点计算后的CSS样式,用.getPropertyValue('background-image')获取背景图属性的值,最后用正则提取背景图属性值中的图片地址。具体代码如下

function getTagImgs(doc) {
  const htmlCol = [...doc.getElementsByTagName('img')]
  return htmlCol.filter(img => img.currentSrc).map(img => {
    return img.currentSrc
  })
}

function getBgImgs(doc) {
  // 定义一个正则表达式来匹配CSS中的background-image属性值。
  // 该正则可以捕获格式为url("path/to/image")中的路径字符串。
  const srcChecker = /url\(\s*?['"]?\s*?(\S+?)\s*?["']?\s*?\)/i

  // 返回从文档中查询到的所有DOM元素的结果。
  return Array.from(
    Array.from(doc.querySelectorAll('*'))
      .reduce((collection, node) => {
        // 使用window.getComputedStyle方法获取节点的所有计算后的CSS样式。
        let prop = window.getComputedStyle(node, null)
          .getPropertyValue('background-image')
        let match = srcChecker.exec(prop)
        if (match) {
          collection.add(match[1])
        }
        return collection
      }, new Set())
  )
}

内容脚本获取到所有图片地址后,可以通过官方API chrome.runtime.sendMessage,然后在popup页面通过chrome.runtime.onMessage.addListener接收到所有图片地址。测试可行。

优化

        问题:嵌套的iframe内的图片资源无法获取

        解决方案:通过document.getElementsByTagName('iframe')获取所有iframe,遍历所有iframe通过contentWindow.document获取当前iframe的document(必须和父级是同源的才能访问iframe的document),然后递归处理所有iframe。

function findImages() {
  let srcList = []
  const loopIframe = doc => {
    const imgList = getTagImgs(doc)
    const imgBgList = getBgImgs(doc)
    srcList = [...new Set([...srcList, ...imgList, ...imgBgList])]

    const iframeCollection = doc.getElementsByTagName('iframe')
    if (iframeCollection?.length > 0) {
      const list = [...iframeCollection]
      list.forEach(item => {
        const curDoc = item?.contentWindow?.document
        if (curDoc) {
          loopIframe(curDoc)
        }
      })
    }
  }

  loopIframe(document)
  return srcList
}

再优化

        问题:伪元素无法直接获取,无法拿到伪元素的背景图

        解决方案:通过window.getComputedStyle(node, '::after')、window.getComputedStyle(node, '::before')获取每个元素的伪元素样式,通过getPropertyValue('background-image')获取伪元素样式的属性值。

function getBgImgs(doc) {
  // 定义一个正则表达式来匹配CSS中的background-image属性值。
  // 该正则可以捕获格式为url("path/to/image")中的路径字符串。
  const srcChecker = /url\(\s*?['"]?\s*?(\S+?)\s*?["']?\s*?\)/i

  // 返回从文档中查询到的所有DOM元素的结果。
  return Array.from(
    Array.from(doc.querySelectorAll('*'))
      .reduce((collection, node) => {
        // 使用window.getComputedStyle方法获取节点的所有计算后的CSS样式。
        const prop = window.getComputedStyle(node, null)
          .getPropertyValue('background-image')
          const match = srcChecker.exec(prop)
        if (match) {
          collection.add(match[1])
        }
        const afterProp = window.getComputedStyle(node, '::after')
          .getPropertyValue('background-image')
          console.log('afterProp', afterProp)
        const afterMatch = srcChecker.exec(afterProp)
        if (afterMatch) {
          collection.add(afterMatch[1])
        }
        const beforeProp = window.getComputedStyle(node, '::before')
          .getPropertyValue('background-image')
        const beforeMatch = srcChecker.exec(beforeProp)
        if (beforeMatch) {
          collection.add(beforeMatch[1])
        }
        return collection
      }, new Set())
  )
}

再再优化

        可以通过PerformanceObserver监控所有资源的加载,然后从所有资源中过滤出需要的图片资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值