Shadow-root是什么
Shadow DOM(Shadow-root 的基础技术)是 Web 组件(Web Components)规范的一部分,它允许将一个元素的子树(DOM 子结构)封装起来,使其与主文档(DOM)隔离。Shadow-root 是一个特殊的 DOM 元素,它充当封装的根节点,将组件内部的 DOM 结构与外部 DOM 隔离开来。
Shadow DOM 的主要目标是实现封装,以便开发人员可以构建可重用的自定义元素,而无需担心样式和脚本的冲突。通过使用 shadow-root,可以确保组件内部的样式不会影响主文档,同时也可以防止主文档的样式影响组件。
在创建 shadow-root 时,可以选择两种模式:open
或 closed
。在 open
模式下,可以从主文档访问 shadow-root,这有助于调试和开发。在 closed
模式下,shadow-root 无法从主文档访问,从而提供更严格的封装。
简而言之,shadow-root 是一种实现 DOM 封装的技术,用于创建可重用和独立的自定义 Web 组件。
如何获取Shadow-root元素close模式时的数据
要获取 shadow-root 元素内的数据,您需要使用支持 JavaScript 执行的库,如 Selenium(Python)或 Puppeteer(Node.js)。这里以 Node.js 的 puppeteer 为例,说明如何获取 shadow-root 内的数据。
示例代码
const puppeteer = require('puppeteer');
const url = 'https://mil.huanqiu.com/';
const executablePath = './chromedriver.exe';
// const executablePath = './Chrome.app/Contents/MacOS/Google Chrome';
(async () => {
try {
const browser = await puppeteer.launch({
executablePath: executablePath, // 设置 Chrome 可执行文件路径
headless: false,
});
const script = `
(function() {
Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function () {
return this._attachShadow({mode:'open'});
};})();`;
const page = await browser.newPage();
await page.evaluateOnNewDocument(script); // 注入时机:请求前注入替换属性方法
await page.goto(url);
await page.waitForTimeout(3000); // 等待 3 秒
const getNestedShadowRootData = async (selectors, index = 0) => {
return await page.evaluate((selectors, index) => {
const findShadowRoot = (element, selectors, index) => {
if (!element || index >= selectors.length) {
return element ? element.innerHTML : null;
}
const shadowHost = element.querySelector(selectors[index]);
if (!shadowHost) {
return null;
}
const shadowRoot = shadowHost.shadowRoot;
return findShadowRoot(shadowRoot, selectors, index + 1);
};
return findShadowRoot(document, selectors, index);
}, selectors, index);
};
// 多层 shadow-root遍历获取数据
const shadowHostSelectors = [
'body > channel-container-template',
'div > div > div > div.col-10 > div.layout > div.layout-center > layout-block-template:nth-child(2)',
'div > layout-bd-template',
'div > sketch-feed-template'
];
const nestedShadowRootData = await getNestedShadowRootData(shadowHostSelectors);
console.log('Nested shadow-root data:', nestedShadowRootData);
await browser.close();
} catch (error) {
console.error('An error occurred:', error);
}
})();