Javascript 使用样式捕获当前dom时缺少样式元素

Javascript 使用样式捕获当前dom时缺少样式元素,javascript,css,dom,Javascript,Css,Dom,我试图使用Selenium捕获当前有效的dom样式。其想法是创建一个引擎,可以捕获它在不同点处理的网页的状态(主要用于测试目的)。因此,我希望有一个跨平台的解决方案(不包括IE),这就是为什么我选择纯javascrit解决方案的原因。因此,我最终要做的是使用Webdriver.executeScript从Selenium调用一个脚本,它允许我提取dom,并在特定点内联所有样式。对于脚本,我从另一个答案中得到了很大的启发,我在网站上找到了这个答案,但是我找不到返回的链接 虽然解决方案可以正常工作,

我试图使用Selenium捕获当前有效的dom样式。其想法是创建一个引擎,可以捕获它在不同点处理的网页的状态(主要用于测试目的)。因此,我希望有一个跨平台的解决方案(不包括IE),这就是为什么我选择纯javascrit解决方案的原因。因此,我最终要做的是使用
Webdriver.executeScript
从Selenium调用一个脚本,它允许我提取dom,并在特定点内联所有样式。对于脚本,我从另一个答案中得到了很大的启发,我在网站上找到了这个答案,但是我找不到返回的链接

虽然解决方案可以正常工作,但仍然存在一些问题,主要是填充和字体。代码如下:

const getCurrentDom = (function () {
    let defaultStylesByTagName = {};

    const noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};
    const ignoreTags = new Set(['SCRIPT', 'STYLE', 'LINK']);
    const tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];

    for (let i = 0; i < tagNames.length; i++) {
        if(!noStyleTags[tagNames[i]]) {
            defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
        }
    }

    function computeDefaultStyleByTagName(tagName) {
        let defaultStyle = {};

        const element = document.body.appendChild(document.createElement(tagName));
        const computedStyle = getComputedStyle(element);

        for (let i = 0; i < computedStyle.length; i++) {
            defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
        }

        document.body.removeChild(element);
        return defaultStyle;
    }

    function hasTagName(node, tagName){
        if(node.tagName === undefined){
            return false;
        }

        return node.tagName.toUpperCase() === tagName.toUpperCase();
    }

    function getDefaultStyleByTagName(tagName) {
        tagName = tagName.toUpperCase();

        if (!defaultStylesByTagName[tagName]) {
            defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
        }

        return defaultStylesByTagName[tagName];
    }

    function isIgnored(node){
        if(node === undefined){
            return true;
        }
        
        if(node.tagName === undefined){
            return false;
        }

        return ignoreTags.has(node.tagName.toUpperCase());
    }

    function isComputeStyle(node){
        if(node.tagName === undefined){
            return false;
        }

        return node instanceof Element && !noStyleTags[node.tagName.toUpperCase()];
    }

    function computeImageNode(node){
        let img = document.createElement("img");

        if(node.alt != ""){
            img.alt = node.alt;
        }
        
        if(node.id != ""){
            img.id = node.id;
        }

        img.width = node.width;
        img.height = node.height;
        img.class = node.class;

        console.log(img.outerHTML);

        return img;
    }

    function deepCloneWithStyles (node) {
        if(hasTagName(node, "img")){
            return computeImageNode(node);
        }

        const clone = node.cloneNode(false);

        if (isComputeStyle(node)) {
            const defaultStyle = getDefaultStyleByTagName(node.tagName);
            const computedStyle = getComputedStyle(node);
            updateStyle(clone, computedStyle, defaultStyle);
            clone.style.font = node.style.font;
        }

        updateStyle(clone, node.style, {});

        for (let child of node.childNodes){
            if(!isIgnored(child)){
                clone.appendChild(deepCloneWithStyles(child));
            }
        }

        return clone;
    }

    function updateStyle(node, styles, defaultStyle){
        if(styles === undefined){
            return;
        }

        for (let i = 0, l = styles.length; i < l; ++i) {
            const cssPropName = styles[i];

            if(defaultStyle !== undefined && styles[cssPropName] === defaultStyle[cssPropName]){
                continue;
            }

            if (styles[cssPropName] !== null && styles[cssPropName] !== "") {
                node.style[cssPropName] = styles[cssPropName];  
            }
        }
    }

    return function computeDom() {
        let node = document.documentElement;
        return deepCloneWithStyles(node).outerHTML;
    }
})();
const getCurrentDom=(函数(){
让defaultStylesByTagName={};
const noStyleTags={“BASE”:true,“HEAD”:true,“HTML”:true,“META”:true,“NOFRAME”:true,“NOSCRIPT”:true,“PARAM”:true,“SCRIPT”:true,“STYLE”:true,“TITLE”:true};
const ignoreTags=新集合(['SCRIPT','STYLE','LINK']);
const标记名=[“A”、“ABBR”、“ADDRESS”、“AREA”、“ARTICLE”、“side”、“AUDIO”、“B”、“BASE”、“BDI”、“BDO”、“BLOCKQUOTE”、“BODY”、“BR”、“BUTTON”、“CANVAS”、“CAPTION”、“CENTER”、“CITE”、“CODE”、“COL”、“COLGROUP”、“COMMAND”、“DATALIST”、“DD”、“DEL”、“DETAILS”、“DFN”、“DIV”、“DL”、“DT”、“EM”、“EMBED”、“FIELDSET”、“FIGCAPTION”、“FIGCAPTION”、“fig”、“FONT”、“FOOTER”、“FORM”、“H1”、“H2”、“H3”、“H4”、“H5”、“H6”“头”、“头”、“HGROUP”、“HR”、“HTML”、“I”、“IFRAME”、“IMG”、“INPUT”、“INS”、“KBD”、“KEYGEN”、“LABEL”、“legen”、“LI”、“LINK”、“MAP”、“MARK”、“MATH”、“MENU”、“META”、“METER”、“NAV”、“NOBR”、“NOSCRIPT”、“OBJECT”、“OL”、“OPTION”、“OPTION”、“opt”、“OPTGROUP”、“OUTPUT”、“P”、“PARAM”、“PRE”、“PROGRESS”、“Q”、“RP”、“RT”、“RUBY”、“S”、“SAMP”、“SCRIPT”、“SECTION”、“SELECT”、“SMALL”、“SOURCE”、“SPAN”、“STRONG”,“样式”、“子”、“摘要”、“SUP”、“SVG”、“表格”、“TBODY”、“TD”、“TEXTAREA”、“TFOOT”、“TH”、“THEAD”、“TIME”、“TITLE”、“TR”、“TRACK”、“U”、“UL”、“VAR”、“VIDEO”、“WBR”];
for(设i=0;i
如上所述,问题在于,在处理页边距/填充时,此函数生成的dom的行为似乎有点古怪,字体似乎总是设置为Times New Roman。下面是stackOverflow的一个页面示例:

和使用脚本生成的dom的相同页面:

事实上,没有渲染图像是出于设计,因为我只想保留一个包含所有内容的文件(因此我只保留大小)。但是,正如您在左侧链接上看到的,左侧有一个巨大的填充,在原始图像中不存在,问问题按钮中的空白也是如此