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

PhantomJS 服务端仿浏览器截图

作者头像
不愿意做鱼的小鲸鱼
发布于 2023-07-09 06:12:49
发布于 2023-07-09 06:12:49
46400
代码可运行
举报
文章被收录于专栏:web全栈web全栈
运行总次数:0
代码可运行

背景

在之前开发的一个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包

下载后解压目录如下:

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

2. 测试PhantomJS工具

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
phantomjs.exe rasterize.js https://www.baidu.com/ test.png

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
 @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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
100个Python练手小程序[通俗易懂]
100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python。
全栈程序员站长
2022/08/03
8160
C语言入门经典题目及其答案
【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 2.程序源代码:
风骨散人Chiam
2020/10/28
2.9K0
10个经典的C语言小程序
来源:codeceo 今天给大家分享10个比较基础的C语言的小程序,希望给C语言初学者带来一定帮助。 1、题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足条件的排列。 程序源代码: main() { int i,j,k; printf("\n"); for(i=1;i<5;i++)    /*以下为三重循环*/  for(j=1;j<5;j++)    for (k=1;k
编程范 源代码公司
2018/04/16
2.7K3
7个C语言小程序让你快速入门程序世界
1、题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
老九君
2018/10/25
1.1K0
7个C语言小程序让你快速入门程序世界
C语言经典例题100
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
C语言与CPP编程
2021/04/02
2.9K0
C语言经典例题100
Python入门经典练习题
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
全栈程序员站长
2022/09/06
7210
C语言一百例(11-20)
11,题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子的规律为数列1,1,2,3,5,8,13,21....
紫禁玄科
2022/03/24
4490
C语言程序设计50例(二)(经典收藏)
【程序11】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月    后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21.... 2.程序源代码: 1 #include "stdio.h" 2 #include "conio.h" 3 main() 4 { 5 long f1,f2; 6 int i; 7 f1=f2=1; 8 for(i=1;i<=20;i+
互联网金融打杂
2018/04/03
1.2K0
43道Python经典案例题(有答案)
(2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。
Python学习者
2022/11/15
1.4K0
C语言经典算法题
2. 一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
越陌度阡
2021/10/26
4.7K0
python练习2
题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高    于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提    成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于    40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于    100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数? 1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。       2.程序源代码:
用户8442333
2021/05/24
4260
Python基础训练100题-1
题目:有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?
用户9925864
2022/07/27
2510
100 个 Python 小例子
原题地址:http://www.runoob.com/python/python-100-examples.html,原例为py2.7版本,重写过程中有不少是随意发挥的,重写运行版本:Python3.7。
Python小二
2020/09/08
7860
Python3入门经典100例
最近由于人工智能和编译原理实验,决定要学python3。不为别的,就是因为自己语言基础太差,现学现卖只能用python了。网上看了一圈python的例题,都只有python2的,于是自己决定把python2的例题,手写成python3。希望通过这100道例题,自己能对python3的基础代码能力有一定的掌握。
py3study
2020/01/10
1.9K0
Python练手例子(2)
11、古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
py3study
2020/01/17
5770
C语言程序设计50例(一)(经典收藏)
【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去       掉不满足条件的排列。 1 #include "stdio.h" 2 #include "conio.h" 3 main() 4 { 5 int i,j,k; 6 printf("\n"); 7 for(i=1;i<5;i++) /*以下为三重循环*/ 8 for(j=1;j<5;j+
互联网金融打杂
2018/04/03
8850
python练习10
【程序10】 题目:打印楼梯,同时在楼梯上方打印两个笑脸。 1.程序分析:用i控制行,j来控制列,j根据i的变化来控制输出黑方格的个数。 2.程序源代码:
用户8442333
2021/05/24
2710
【14】Python100例基础练习(1
例1: 有四个数字:1、2、3、4能组成多少个互不相同且无重复的数字的三位数?各是多少? 审题: 1.去重 2.计算总数 程序代码: 方法1:
py3study
2020/01/07
6070
Python 流程控制与循环体
单分支结构: 单分支结构的判断是最简单的一种形式,如果满足条件则执行,否则跳过IF语句.
王 瑞
2022/12/28
4720
100道Python练习题,建议收藏练习
链接丨https://github.com/RichardFu123/Python100Cases
张俊红
2021/01/18
1.6K0
相关推荐
100个Python练手小程序[通俗易懂]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档