如何递归遍历页面及嵌套iframe,获取所有<a>标签元素?
解决嵌套iframe内标签的遍历问题
原代码仅能处理第一层iframe,无法获取嵌套iframe中的标签,核心问题在于只处理了当前层级的iframe,没有递归遍历iframe内部的所有子元素(包括嵌套的iframe)。
原代码问题分析
原代码在处理iframe时,仅将root替换为iframe的body,但没有递归遍历这个body下的所有元素(包括嵌套的iframe),而是直接查找当前层级的标签,导致嵌套结构中的iframe被遗漏。
修改后的代码
const subtreeSet = (root, theset) => { if (!theset) theset = new Set(); if (!root || theset.has(root)) return theset; theset.add(root); // 处理Shadow DOM if (root.shadowRoot) { Array.from(root.shadowRoot.children).forEach(child => subtreeSet(child, theset)); } else { let currentRoot = root; // 处理当前节点是iframe的情况 if (currentRoot.tagName === 'IFRAME') { try { currentRoot = currentRoot.contentDocument.body; theset.add(currentRoot); } catch (err) { currentRoot = null; // 跨域无法访问,直接跳过 } } // 递归遍历当前节点下的所有子元素(包括嵌套的iframe) if (currentRoot && currentRoot.children) { Array.from(currentRoot.children).forEach(child => subtreeSet(child, theset)); } // 收集当前层级的<a>标签 if (currentRoot && currentRoot.getElementsByTagName) { for (const link of currentRoot.getElementsByTagName('a')) { theset.add(link); } } } return theset; } // 调用并提取所有<a>标签的链接 const allElements = subtreeSet(document); const allLinks = Array.from(allElements).filter(el => el.tagName === 'A').map(a => a.href); console.log(allLinks);
修改说明
- 递归遍历所有子元素:新增遍历当前节点所有子元素的逻辑,确保嵌套的iframe能被递归处理,不会遗漏深层结构。
- 分离递归与标签收集:先处理所有子节点(包括iframe),再收集当前层级的标签,保证每个层级的元素都被遍历到。
- 优化链接提取:最后通过过滤集合中的元素,直接提取所有标签的
href属性,更贴合获取所有链接的需求。
注意:浏览器的同源策略会限制跨域iframe的
contentDocument访问,这类iframe内的链接无法获取,属于正常安全限制。
内容的提问来源于stack exchange,提问作者Sergiy
相关产品推荐
相关产品推荐

