回溯-获取页面的html

我们要做页面的回溯,首先我们需要获取当前页面的所有的html内容然后在需要回溯的时候重新模拟回放出来,当然你可能会说你可以直接通过iframe把目前页面引入也是可以的。这个方式不是不可以,只不过限制太多了,比如,登录状态就是个问题,而直接获取页面的内容在模拟回放就没有这个问题。当然了,还有很多的问题了~

要获取html内容,我们可能想到的就是innerHTML或者outerHTML这两个方法了。

1
const pageHTML = document.documentElement.outerHTML

通过上述方法我们就可以拿到想要的,然而当我们把获取内容放到本地测试的时候发现了问题,页面是不展示的。当然看有的是展示的,为什么呢?通过对代码的分析的出来,有些css和js的引入是相对当前域名的,例如:

1
2
3
<link href="/css/a.css"/>
<script src="./js/b.js"></script>
<img src="./images/xxx.jpg" />

找出问题下面就是解决问题了,如果把上面的换成下面的样子呢?

1
2
3
<link href="https:xxxx.com/css/a.css"/>
<script src="https:xxxx.com/js/b.js"></script>
<img src="https:xxxx.com/images/xxx.jpg" />

第一感觉还是正则,使用正则找出所有的情况然后进行替换。这种方案肯定是可行的,但是需要考虑的比较多,咱们今天使用的是另外一个方案-template方式。

1
2
3
<template>
<img src="./images/xxx.jpg" />
</template>

如果你不了解template可以去看看文档,这里我们简单的引用下文档:

HTML 内容模板(<template>)元素是一种用于保存客户端内容机制,该内容在加载页面时不会呈现,但随后可以 (原文为 may be) 在运行时使用 JavaScript 实例化。

将模板视为一个可存储在文档中以便后续使用的内容片段。虽然解析器在加载页面时确实会处理<template>元素的内容,但这样做只是为了确保这些内容有效;但元素内容不会被渲染。

此元素仅包含全局属性。但, HTMLTemplateElement 有个属性: content , 这个属性是只读的DocumentFragment 包含了模板所表示的 DOM 树。

通过官方的文档我们知道,template就是个用于存放内容的模板并且不会展示内容,我们以前使用script和textarea来做现在有官方的标签了就更强大了。

1
2
3
4
5
const pageHtml = document.documentElement.outerHTML;
const template = document.createElement('template')
template.innerHTML = pageHtml
// 处理下代码,例如,原来相对路径的都改成绝对路径
const scripts = template.content.querySelectorAll("script")

从上面可以看出,content可以让我们使用dom操作,非常的简单。下面我们写出一个完整的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getPageCodeAndEncode() {
// 获取源码,创建template模板,把源码放入模板
const pageHtml = document.documentElement.outerHTML;
let template = document.createElement('template')
template.innerHTML = pageHtml
// 处理下代码,例如,原来相对路径的都改成绝对路径
const scripts = template.content.querySelectorAll("script")
const links = template.content.querySelectorAll("link")
const images = template.content.querySelectorAll("img")
links.forEach((el) => {
el.href = el.href
})
scripts.forEach((el) => {
el.src = el.src
})
images.forEach((el) => {
el.src = el.src
})
const newHtmlStr = template.innerHTML
template = null
return encodeURIComponent(newHtmlStr)
}

上面是把html获取到然后处理成我们想要的样子然后返回,如果你看了template的官方文档会发现,它里面不支持的标签还是有一些的。比如:html,head,body。所以我们输出的内容看着就是没有上面的三种标签的。这肯定不行我们怎么办呢?

这时候我们需要使用 DOMParser.parseFromString()了,不了解的可以看下官方的文档

1
2
3
4
5
6
7
8
9
function parsePageCode(code) {
const decode = decodeURIComponent(code)
const dom = new DOMParser().parseFromString(decode, 'text/html');
return {
dom,
domStr: dom.documentElement.outerHTML
}
}

上面方法是把处理好的代码转成标准的html,可以使用document.write写入文档即可。

1
2
3
4
5
6

function parsePageCode(code) {
const decode = decodeURIComponent(code)
const dom = new DOMParser().parseFromString(decode, 'text/html');
document.write(dom.documentElement.outerHTML)
}

有了以上两个方法我们就可以来我们本地重新模拟回放页面了。


回溯-获取页面的html
http://yoursite.com/2022/06/14/record-page/
作者
昂藏君子
发布于
2022年6月14日
许可协议