前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PhantomJS 服务端仿浏览器截图

PhantomJS 服务端仿浏览器截图

作者头像
不愿意做鱼的小鲸鱼
发布2023-07-09 14:12:49
3060
发布2023-07-09 14:12:49
举报
文章被收录于专栏:web全栈web全栈

背景

在之前开发的一个VisualDrag低代码拖拽模板中,每次保存需要截一张封面图进行保存用来做缩略图预览。在画布上的东西直接转成canvas很方便,直接html2canvas就可以了,但是像浏览器这种元素就行不通了,因为浏览器加载得到资源是超链接的,无法获取第三方网页的html,如果在js中直接请求全部都是跨域了,尝试了很多种方法也行不通,所以想到了一个方法另辟蹊径,把超链接的浏览器截图交给服务端处理,web端直接传给服务端超链接和截图的位置大小,服务端截图完后直接返回给web端图片地址或者数据流,然后截图的时候直接把图片替换浏览器放在画布上,就可以截图成功了。

实现的方案有很多,比如:PhantomJS,Selenium WebDriver,HtmlUnit,Puppeteer等,大致的思路都是在服务端静默的模仿打开浏览器,从而进行截图。 由于服务端一般使用java,本次实现的方案是使用java + PhantomJS + rasterize.js

实现步骤

1. 下载截图工具PhantomJS

简介: PhantomJS是一个基于webkit的javaScript API。它使用QtWebKit作为它核心浏览器的功能,使用webkit来编译解释执行javaScript代码。任何你可以基于在webkit浏览器做的事情,它都能做到。它不仅是个隐性的浏览器,提供了诸如css选择器、支持wen标准、DOM操作、json、HTML5等,同时也提供了处理文件I/O的操作,从而使你可以向操作系统读写文件等。phantomJS的用处可谓非常广泛诸如网络监测、网页截屏、无需浏览器的wen测试、页面访问自动化等。

各个平台下载地址:https://phantomjs.org/download.html 也可以网盘下载:https://pan.baidu.com/s/1mLHdwlSzyIGsiIYBeZY0eg 提取码 :ehim

选择下载windows的PhantomJS包

下载后解压目录如下:

PhantomJS 服务端仿浏览器截图-左眼会陪右眼哭の博客
PhantomJS 服务端仿浏览器截图-左眼会陪右眼哭の博客

其中bin目录是PhantomJS工具的执行环境 examples是许多该工具执行时需要的不同场景的demo,比如下面我用到的rasterize.js 。

2. 测试PhantomJS工具

执行脚本如下(我把rasterize.js放在了bin目录):

代码语言:javascript
复制
phantomjs.exe rasterize.js https://www.baidu.com/ test.png

执行完之后就在bin当前目录生成了一直test.png的图片。

PhantomJS 服务端仿浏览器截图-左眼会陪右眼哭の博客
PhantomJS 服务端仿浏览器截图-左眼会陪右眼哭の博客

当然也可以自己指定参数位置等。 examples文件夹下面的rasterize.js也不是很复杂,可以自己看代码进行传参,大致就是传例如 宽*高px 的参数,然后js脚本中会对参数进行分割处理,最后变成下面的命令模式进行执行:phantomjs.exe + rasterize.js + 链接url + 截图保存位置 + X轴 + Y轴 + 宽 + 高

所以业务需要,我仿照rasterize.js自己写了一个截图脚本:

代码语言:javascript
复制
"use strict";
var page = require('webpage').create(),
  system = require('system');
/*
用法:
1. 默认使用方法为(两个参数): phantomjs.exe + rasterize.js + 链接url + 截图保存位置
2. (七个参数): phantomjs.exe + rasterize.js + 链接url + 截图保存位置 + X轴 + Y轴 + 宽 + 高
*/

page.viewportSize = {
  width: 600,
  height: 600
};
page.clipRect = {
  top: 0,
  left: 0,
  width: 600,
  height: 600
};
var address = system.args[1];
var output = system.args[2];
var clipRect;

if (system.args.length > 3) {
  var x = parseInt(system.args[3]);
  var y = parseInt(system.args[4]);
  var width = parseInt(system.args[5]);
  var height = parseInt(system.args[6]);
  page.viewportSize = {
    width: width,
    height: height
  };
  clipRect = {
    top: y,
    left: x,
    width: width,
    height: height
  };
}

page.open(address, function (status) {
  if (status !== 'success') {
    console.log('Unable to load the address!');
    phantom.exit(1);
  } else {
    window.setTimeout(function () {
      page.clipRect = clipRect;
      page.render(output);
      phantom.exit();
    }, 200);
  }
});

用法:

  1. 默认使用方法为(两个参数): phantomjs.exe + rasterize.js + 链接url + 截图保存位置
  2. (七个参数): phantomjs.exe + rasterize.js + 链接url + 截图保存位置 + X轴 + Y轴 + 宽 + 高

3. 在java项目中集成PhantomJS

ScreenshotUtil工具类

代码语言:javascript
复制
package com.team.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * Created by tao.
 * Date: 2022/1/24 16:56
 * 描述: 根据网页地址转换成图片
 */

@Component
@Slf4j
public class ScreenshotUtil {
    public static String phantomjsPath;

    @Value("${phantomjs}")
    public void setPhantomjs(String phantomjs) {
        phantomjsPath = phantomjs;
    }

    public static String path;

    @Value("${file.windows.path}")
    public void setPath(String p) {
        path = p;
    }

    private static String BLANK = " ";
    // 下面内容可以在配置文件中配置

    // 执行cmd命令
    public static String cmd(String imgagePath, String url, String width, String height) {
        String binPath = phantomjsPath + "bin/phantomjs.exe";// 插件引入地址
        String jsPath = phantomjsPath + "examples/rasterize.js";// js引入地址
        // return binPath + BLANK + jsPath + BLANK + url + BLANK + imgagePath;
        return binPath + BLANK + jsPath + BLANK + url + BLANK + imgagePath + BLANK + "0" + BLANK + "0" + BLANK + width + BLANK + height;
    }

    //关闭命令
    public static void close(Process process, BufferedReader bufferedReader) throws IOException {
        if (bufferedReader != null) {
            bufferedReader.close();
        }
        if (process != null) {
            process.destroy();
            process = null;
        }
    }

    /**
     * @param url
     * @throws IOException
     */
    public static String screenshot(String url, String width, String height) throws IOException {
        String tempPath = path;// 图片保存目录
        String imgagePath = tempPath + "缩略图/" + System.currentTimeMillis() + ".png";//图片路径
        System.out.println(imgagePath);
        //Java中使用Runtime和Process类运行外部程序
        Process process = Runtime.getRuntime().exec(cmd(imgagePath, url, width, height));
        InputStream inputStream = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String tmp = "";
        while ((tmp = reader.readLine()) != null) {
            close(process, reader);
        }
        System.out.println("url截图成功");
        return imgagePath;
    }
}

其中文件的路径我放在了配置文件里

测试如下:

代码语言:javascript
复制
 @Test
    public void test() throws Exception {
        String url = "https://www.baidu.com/";//以百度网站首页为例
        ScreenshotUtil.screenshot(url, "400", "300");
    }

执行代码就可以在指定目录下获取url的400*300的截图。

总结

服务端使用PhantomJS工具进行对网页的截图还是行得通的,但是截图的过程需要几秒钟,响应稍微有些慢,有兴趣可以对比一下其他网页的截图方案。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现步骤
    • 1. 下载截图工具PhantomJS
      • 2. 测试PhantomJS工具
        • 3. 在java项目中集成PhantomJS
        • 总结
        相关产品与服务
        腾讯云服务器利旧
        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档