返回

网页首图/缩略图高效获取:JS实战方案

java

网页首图/视频缩略图获取方案

获取网页上的第一张可见图片或视频缩略图是一个常见的需求,常见于生成网页预览、社交媒体分享等场景。但简单的选取HTML中的第一个<img>标签并不总是准确。比如,许多网页结构复杂,存在隐藏的图片或占位的图像。而且,视频的缩略图获取逻辑也与图片有所不同。下文将分析问题并提出更有效的解决方案。

问题分析

通常的代码,类似上述示例,只选取第一个<img>标签,它不一定是视觉上最重要的或者用户真正看到的。

  1. 非可见图像: 网页中可能会有隐藏的图像,这些图片不会被用户看到。这些隐藏的图像很可能位于实际内容的顶部。例如使用 display: none 或者位于容器外的元素内的图片。

  2. Lazy Load图片: 许多网页使用了懒加载技术。图片最初的src属性为空或者占位符,当图片滚动到可视区域时才会被真正的URL替换。选取HTML中最初的图片属性时可能会捕获不到真正的缩略图。

  3. 视频缩略图处理: 对于视频,video标签并不总是包含缩略图URL,很多时候,缩略图需要从其他属性,或者使用媒体 API 进行加载。例如 poster 属性或者通过调用视频API接口来取得。

  4. SVG图像和背景图像: 一些网站可能使用 SVG 图形或者CSS背景图像,这些元素不在 <img>标签范围内,普通的图片选择器不会处理。

解决方案

要准确找到网页的第一张可见图片或者视频缩略图,需要采用更完善的策略。下面分步骤讨论不同的方案。

1. 使用可视区域检测

首先,需要筛选出当前可视区域中的图片。只检查HTML中第一个 img 标签不足以找出真正的第一张可见图像,还需要判断这个图像是否确实出现在用户的视野之中。
可以使用浏览器API来检查图片是否可见,比如 Element.getBoundingClientRect() 方法。 这个方法可以计算元素相对于视口的位置和尺寸。如果一个元素部分或完全在视口内,就被认为是可见的。

步骤:

  1. 获取所有图片元素: 使用 CSS 选择器获取所有的img标签。
  2. 循环遍历图片: 对于每个img标签, 获取其位置信息。
  3. 视口检测: 通过 getBoundingClientRect 获得元素位置, 然后判断该元素是否与浏览器视口有重叠。如果图片的任何部分在屏幕可见范围内,即视为该图片可见。
  4. 优先选择大的可视区域图片: 如果多个图片都可见,优先选择在可视区域内显示面积较大的图片,可能更符合缩略图的目标。

代码示例: (JavaScript, 此处代码为概念演示,请自行处理页面加载完成、异步图片加载等边界情况)

function getFirstVisibleImage() {
    const images = document.querySelectorAll('img');
    let bestImage = null;
    let bestArea = 0;

    images.forEach(img => {
        const rect = img.getBoundingClientRect();
        if(rect.width <=0 || rect.height <=0) {
            return; // 如果图片大小为0,排除
        }

        const isVisible = rect.top < window.innerHeight && rect.left < window.innerWidth && rect.bottom > 0 && rect.right > 0;


        if (isVisible) {
             const area = rect.width * rect.height;
             if( area > bestArea){
                 bestImage = img;
                 bestArea = area;
             }

         }

    });

     if (bestImage){
        return bestImage.src
     }
     return null; // No visible images
}


2. 视频缩略图处理

处理视频缩略图时,先要查找页面的所有video标签。尝试使用以下策略获取缩略图:

步骤:

  1. 获取所有视频元素: 使用 CSS 选择器获取所有的video标签。
  2. 检查poster属性: 优先使用video标签上的poster属性。此属性通常直接包含缩略图 URL。
  3. 媒体API: 如果没有poster属性, 有些时候视频的预览图会在媒体接口返回, 这部分需要使用媒体相关的JS API获取(较复杂,此处不做展示)
  4. 图片兜底: 如果在当前网页无法找到视频对应的缩略图,可以使用类似步骤1 的图片选取逻辑来选择备用方案,使用页面的主要图片作为备用。

代码示例 (JavaScript)

function getFirstVideoThumbnail() {
    const videos = document.querySelectorAll('video');
    if(videos.length > 0){
        for (const video of videos){
          if(video.poster){
            return video.poster;
          }
          // 添加媒体 API 获取逻辑,此处省略复杂逻辑
        }

    }
    return null
}

3. 处理 Lazy Load 图片

对于懒加载的图片, 通常真实的 URL 不会存在在img 元素的 src 属性中。 有时会存储在其他属性(如data-src), 可以在遍历时优先检测该属性的值。另外可以考虑结合 步骤一 中的可视区域检查逻辑, 尽早加载图片, 或延迟到检测到图片完全加载之后再取得真实URL

代码示例 (JavaScript,示例属性名称,需要根据实际页面调整)

 function getFirstImageWithLazyload(){

        const images = document.querySelectorAll('img');
         let bestImage = null;
        let bestArea = 0;

         images.forEach(img => {
         const rect = img.getBoundingClientRect();

           if(rect.width <=0 || rect.height <=0) {
                 return; // 如果图片大小为0,排除
             }
            const isVisible = rect.top < window.innerHeight && rect.left < window.innerWidth && rect.bottom > 0 && rect.right > 0;

             if(isVisible){
                  const src = img.dataset.src || img.src
                  if(src){
                        const area = rect.width * rect.height;
                         if( area > bestArea){
                         bestImage = img;
                            bestArea = area;
                            }
                  }
            }

        })
        if (bestImage){
            return bestImage.dataset.src || bestImage.src;
        }
          return null
}

安全建议

  1. 验证URL: 获取到的 URL,最好验证一下其合法性,防止加载非法或者恶意的资源。
  2. 避免大图片: 如果目标是获取缩略图,要考虑到一些图片尺寸过大, 做好适当的图片大小裁剪,确保展示效果并提高加载速度。

结论

获取网页的首张图片或视频缩略图并不简单。只选取第一个imgvideo标签是不够的,我们需要结合元素可视性、懒加载以及视频特有的poster属性和API进行处理。采用上述方案能够提高准确度,并且适应各种网页的结构变化。结合JavaScript进行动态的处理能够较好的适配各类复杂网页。