如何过滤页面上可见的 HTML 节点并提取字体信息
在前端开发、内容提取、页面分析等场景中,我们常常需要从页面中筛选出可见的HTML节点,并进一步提取这些节点使用的字体信息。本文将详细介绍完整的实现思路与具体代码实现。
一、核心思路概述
整个流程可以分为两个核心步骤:
第一步:过滤页面中所有HTML节点,筛选出用户可见的节点
第二步:针对可见节点,提取其最终应用的字体相关信息
二、过滤可见HTML节点
判断一个HTML节点是否可见,需要综合多个维度进行判断,常见的不可见场景包括:节点被隐藏、节点尺寸为0、节点脱离可视区域等。以下是判断节点可见性的核心逻辑:
2.1 可见性判断规则
节点的
display样式不为none节点的
visibility样式不为hidden或collapse节点的
opacity大于0节点的宽度和高度均大于0
节点的位置在浏览器当前可视区域内(或至少部分在可视区域内)
节点本身不是隐藏类型的表单元素(如
type="hidden"的<input>标签)
2.2 可见节点过滤代码实现
使用JavaScript实现可见节点过滤的代码如下:
/**
* 判断单个节点是否可见
* @param {HTMLElement} node 待判断的DOM节点
* @returns {boolean} 节点是否可见
*/
function isNodeVisible(node) {
// 排除非元素节点
if (node.nodeType !== 1) return false;
// 检查隐藏类型表单元素
if (node.tagName === 'INPUT' && node.type === 'hidden') return false;
const style = window.getComputedStyle(node);
// 检查display、visibility、opacity
if (style.display === 'none') return false;
if (style.visibility === 'hidden' || style.visibility === 'collapse') return false;
if (parseFloat(style.opacity) 0 && rect.left < viewWidth && rect.bottom > 0 && rect.top < viewHeight;
if (!isInView) return false;
return true;
}
/**
* 获取页面所有可见节点
* @returns {HTMLElement[]} 可见节点数组
*/
function getVisibleNodes() {
// 获取页面所有元素节点
const allNodes = Array.from(document.querySelectorAll('*'));
// 过滤出可见节点
return allNodes.filter(node => isNodeVisible(node));
}三、提取可见节点的字体信息
节点的字体信息可能来自本身的内联样式、页面样式表、继承的父节点样式等,使用window.getComputedStyle可以获取节点最终应用的计算样式,从而得到准确的字体相关信息。
3.1 可提取的字体相关属性
常见的字体相关计算样式属性包括:
font-family:字体族font-size:字体大小font-weight:字体粗细font-style:字体样式(如斜体)line-height:行高letter-spacing:字符间距
3.2 字体信息提取代码实现
结合之前的可见节点过滤逻辑,提取可见节点字体信息的代码如下:
/**
* 提取单个节点的字体信息
* @param {HTMLElement} node 待提取的DOM节点
* @returns {Object} 字体信息对象
*/
function getNodeFontInfo(node) {
const style = window.getComputedStyle(node);
return {
fontFamily: style.fontFamily,
fontSize: style.fontSize,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle,
lineHeight: style.lineHeight,
letterSpacing: style.letterSpacing
};
}
/**
* 获取所有可见节点的字体信息
* @returns {Array} 可见节点及对应字体信息数组
*/
function getAllVisibleNodesFontInfo() {
const visibleNodes = getVisibleNodes();
return visibleNodes.map(node => ({
node: node,
// 补充节点基础信息,方便后续定位
nodeTag: node.tagName.toLowerCase(),
nodeId: node.id || '',
nodeClass: node.className || '',
fontInfo: getNodeFontInfo(node)
}));
}四、实际使用示例
在页面控制台中执行以下代码,即可获取所有可见节点的字体信息,并打印到控制台:
// 执行获取所有可见节点字体信息
const visibleNodesFontInfo = getAllVisibleNodesFontInfo();
console.log('页面可见节点字体信息:', visibleNodesFontInfo);
// 示例:筛选出字体大小大于16px的可见节点
const largeFontNodes = visibleNodesFontInfo.filter(item => {
const fontSize = parseFloat(item.fontInfo.fontSize);
return fontSize > 16;
});
console.log('字体大于16px的可见节点:', largeFontNodes);五、注意事项
如果页面存在iframe,上述代码默认只能获取当前文档的节点,跨域iframe无法访问其内容
部分节点可能设置了
overflow: hidden但内容不完全可见,上述逻辑默认认为只要节点本身在可视区域且尺寸大于0即视为可见,可根据实际需求调整判断规则getComputedStyle返回的值是只读的,且不同浏览器可能返回的格式略有差异,比如fontFamily可能包含多个备选字体,用逗号分隔如果页面动态更新了节点内容或样式,需要重新执行过滤和提取逻辑才能得到最新的结果
六、总结
过滤可见HTML节点并提取字体信息的核心是结合getComputedStyle和getBoundingClientRect方法,先通过样式和尺寸判断节点可见性,再提取计算样式中的字体相关属性。该方案可以覆盖大部分常规页面的节点分析需求,可根据实际业务场景对判断规则进行扩展调整。