js 编写抓取xpath并输出ifram中的xpath 后续会展现层级结构

1 篇文章 0 订阅

需求点: 做一个谷歌插件 通过js 抓取到某页面中的xpath 要求点那些元素 吐出那些元素的xpath并传给后台 这边只展示如何抓取xpath的功能上代码:
1.先抓取所有页面元素:

document.addEventListener("click", function (event) {
    //todo 点击页面时,可以通过加样式改变颜色,也可以加遮罩层
    event.target.style.background = "rgba(213, 0, 0, 0.2)"
    event.target.style.outline = "rgb(199, 0, 0) solid 2px"
    // 绝对路径
    let xpath = new XpathGenerater().generateFullXPath(event.target)
	console.log(event.target)
    // 相对路径
    let relativeXPath = new XpathGenerater().generateRelativeXPath(event.target)
    console.log(`xpath==========${xpath}`)
    console.log(`relativeXPath==========${relativeXPath}`)
})

2.封装逐层递归函数 将点击元素的层级进行剥离 合并

console.log('这是ly showtime!');
class XpathGenerater {
    fullPath = true
    /**
     * 生成给定节点对应的全路径xpath
     * @param {节点} el 
     */
    generateFullXPath(el) {
        return this.generateXPath(el)
    }
    generateXPath(el) {
        let query = ""
        while (el && el.nodeType === Node.ELEMENT_NODE) {
            // 也可以使用nodeName,nodeName包含了tagName
            let component = el.tagName.toLowerCase()
            let index = this.getElementIndex(el)
            // 如果获取相对路径,并且id存在
            if (!this.fullPath && el.id) {
                component += `[@id='${el.id}']`
            }
            if (index >= 1) {
                component += `[${index}]`
            }
            query = '/' + component + query
            // 获取相对路径,尝试执行 xpath 是否为唯一值
            if (!this.fullPath) {
                let temporaryQuery = `/${query}`
                let test = document.evaluate(temporaryQuery, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
                if (test.snapshotLength == 1) {
                    return temporaryQuery
                }
            }

            el = el.parentNode
        }
        return query
    }
    /**
     * 生成给定节点对应的相对路径xpath
     * @param {} el 
     */
    generateRelativeXPath(el) {
        this.fullPath = false
        return this.generateXPath(el)
    }
    /**
     * 获取当前元素节点在上一级节点中的位置
     * 若没有相同类型的兄弟节点,返回 0
     */
    getElementIndex(el) {
        let index = 1
        let sib = el.previousSibling
        while (sib) {
            if (sib.nodeType === Node.ELEMENT_NODE && this.compareTagNameEqual(el, sib)) {
                index++
            }
            sib = sib.previousSibling
        }

        if (index > 1) return index
        sib = el.nextSibling
        while (sib) {
            if (sib.nodeType === Node.ELEMENT_NODE && this.compareTagNameEqual(el, sib)) {
                return 1
            }
            sib = sib.nextSibling
        }
        return 0;
    };
    /**
     * 查看两个元素节点名称是否相同
     */
    compareTagNameEqual(primaryEl, siblingEl) {
        let p = primaryEl, s = siblingEl
        if (this.fullPath) {
            // 获取全路径时,只比较tagName就足够了
            return (p.tagName === s.tagName)
        } else {
            // 当tagName相同时,则也比较id
            return (p.tagName === s.tagName && (!(p.id) || p.id === s.id))
        }
    };
}

获取 ifram中的xpath 暂时使用单ifram的结构 后续博主会进行添加方法 不过类似于ifram之类的程序需要进行二次加载,所以必须找到时机进行抓取元素,这里我选用的是window.onload 其他时机也可以 也可以全局进行监听 后续我会出多ifram嵌套情况的代码,勿催.

window.onload = function(){
	var test = document.getElementById('iframeResult')
	console.log(test.contentWindow.document)
	test.contentWindow.document.addEventListener("click", function (event) {
		//todo 点击页面时,可以通过加样式改变颜色,也可以加遮罩层
		//event.target.style.background = "rgba(213, 0, 0, 0.2)"
		//event.target.style.outline = "rgb(199, 0, 0) solid 2px"
		// 绝对路径
		let xpath = new XpathGenerater().generateFullXPath(event.target)
		console.log(event.target)
		// 相对路径
		let relativeXPath = new XpathGenerater().generateRelativeXPath(event.target)
		console.log(`xpath==========${xpath}`)
		console.log(`relativeXPath==========${relativeXPath}`)
	})
   }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值