如何使用puppeteer获取HTML元素的子元素,以便与其浏览器计算的样式一起创建HTML树?

时间:2019-01-19 12:43:13

标签: javascript html puppeteer

 const e = await page.querySelectorAll('body')
 const htmlTag = await page.evaluate((e) => e.outerHTML, e)
 const compStyle = await page.evaluate((e) => 
             JSON.parse(JSON.stringify(getComputedStyle(e))), e)

使用上面的代码,我得到了body html元素,它是计算样式。就像明智的选择一样,我必须得到它的子元素及其样式。我怎么才能得到它?

1 个答案:

答案 0 :(得分:0)

如果您不介意元素的顺序,则可以使用简单的选择器body *和for循环创建所有元素的数组。

首先,让我们抽象化样式提取器,因为我们将多次使用相同的东西。

// get the styles for particular element
// apply all kind of JSON filtering here
function getElementStyles(elem) {
    return JSON.parse(JSON.stringify(getComputedStyle(elem)))
}

// this will generate a single array containing all elements
function getStyleArray(selector) {
    const styles = []
    const allElements = document.querySelectorAll(selector)
    for (const element of allElements) {
        const style = getElementStyles(element)
        styles.push(style)
    }
    return styles;
}

//usage
getStyleArray('body *')

如果您确实想获取一棵树,则已经有多个库。话虽如此,这是您如何自我复制的方法。我使用了递归来解决这个问题。

// find if element is an element :D
function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;
}

// this will generate a tree style array
// all child elements are accesible using the child key
function getChildStyles(elem) {
    const childStyles = []
    for (let childNode of elem.childNodes) {
        if (isElement(childNode)) {
            const singleChildStyle = getElementStyles(childNode)

            // recursion
            if (childNode.hasChildNodes()) {
                singleChildStyle.child = getChildStyles(childNode)
            }
            childStyles.push(singleChildStyle)
        }
    }
    return childStyles
}

// usage
getChildStyles(document.body)

注意,

  • 可以使用更好的循环和其他排序/搜索方法来改善此情况。
  • 如果页面包含许多元素,这将花费您很多时间。

结果: enter image description here

有效!

让我们申请伪造者,您可以复制粘贴或使用addScriptTag

await page.evaluate(() => {
        // add the scripts we created somewhere and then use them here
        return {
            arrayBased: getStyleArray('body *'),
            treeBased: getChildStyles(document.body)
        }
})