zoukankan      html  css  js  c++  java
  • 利用PhantomJS进行网页截屏,完美解决截取高度的问题

    关于PhantomJS

    PhantomJS 是一个基于WebKit的服务器端 JavaScript API。它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG。PhantomJS可以用于页面自动化,网络监测,网页截屏,以及无界面测试等。

    我们还可以用它来做爬虫哦,大家知道,网页上有些数据是通过执行js渲染出来的,这样的话爬虫去抓取数据的时候就会很麻烦,PhantomJS自带WebKit内核,我们可以利用PhantomJS解决爬虫不能执行js的问题。

    这次要说的是他的截图功能

    下面是官网提供的rasterize.js截图示例:

    var page = require('webpage').create(),
        system = require('system'),
        address, output, size;
    
    if (system.args.length < 3 || system.args.length > 5) {
        console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
        console.log('  paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
        console.log('  image (png/jpg output) examples: "1920px" entire page, window width 1920px');
        console.log('                                   "800px*600px" window, clipped to 800x600');
        phantom.exit(1);
    } else {
        address = system.args[1];
        output = system.args[2];
        page.viewportSize = {  600, height: 600 };
        if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
            size = system.args[3].split('*');
            page.paperSize = size.length === 2 ? {  size[0], height: size[1], margin: '0px' }
                                               : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
        } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
            size = system.args[3].split('*');
            if (size.length === 2) {
                pageWidth = parseInt(size[0], 10);
                pageHeight = parseInt(size[1], 10);
                page.viewportSize = {  pageWidth, height: pageHeight };
                // 通过clipRect可以指定渲染的区域:
                page.clipRect = { top: 0, left: 0,  pageWidth, height: pageHeight };
            } else {
                console.log("size:", system.args[3]);
                pageWidth = parseInt(system.args[3], 10);
                pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
                console.log ("pageHeight:",pageHeight);
                page.viewportSize = {  pageWidth, height: pageHeight };
            }
        }
        if (system.args.length > 4) {
            page.zoomFactor = system.args[4];
        }
        page.open(address, function (status) {
            if (status !== 'success') {
                console.log('Unable to load the address!');
                phantom.exit(1);
            } else {
                window.setTimeout(function () {
                    page.render(output);
                    phantom.exit();
                }, 200);
            }
        });
    }
    

    上面的代码可以进行截图,不过问题就在于,页面的高度需要我们手动指定,那就不方便了。

    在园子里发现有个哥们通过手动设定高度的方法来解决这个问题:http://www.cnblogs.com/xiehuiqi220/p/3551699.html,不过页面的高度没有那么高,渲染的图片下面就会出现大块的留白,也是不够灵活。

    想到PhantomJS本身也可以执行js的,我们可以将页面加载完毕后,获取页面的实际高度,然后重新设定截取的区域,不就可以解决了。

    于是便有了以下代码:

    // 通过在页面上执行脚本获取页面的渲染高度
    var bb = page.evaluate(function () { 
      return document.getElementsByTagName('html')[0].getBoundingClientRect(); 
    });
    // 按照实际页面的高度,设定渲染的宽高
    page.clipRect = {
      top:    bb.top,
      left:   bb.left,
        bb.width,
      height: bb.height
    };
    // 预留一定的渲染时间
    window.setTimeout(function () {
      page.render(file);
      page.close();
      console.log('render ok');
    }, 1000);
    

    改造后的代码如下:

    var page = require('webpage').create(),
        system = require('system'),
        address, output, size;
    
    if (system.args.length < 3 || system.args.length > 5) {
        console.log('Usage: rasterize.js URL filename');
        phantom.exit(1);
    } else {
        address = system.args[1];
        output = system.args[2];
        page.viewportSize = {  1024, height: 600 };
        page.open(address, function (status) {
          // 通过在页面上执行脚本获取页面的渲染高度
          var bb = page.evaluate(function () { 
            return document.getElementsByTagName('html')[0].getBoundingClientRect(); 
          });
          // 按照实际页面的高度,设定渲染的宽高
          page.clipRect = {
            top:    bb.top,
            left:   bb.left,
              bb.width,
            height: bb.height
          };
          // 预留一定的渲染时间
          window.setTimeout(function () {
            page.render(output);
            page.close();
            console.log('render ok');
          }, 1000);
        });
    }
    

    通过执行D:Softwarephantomjs-1.9.7-windows>phantomjs.exe render.js http://cnblogs.com cnblogs.png就可以把博客园首页截取下来了。

    效果如下:

    PhantomJS内置一个小型的Web服务器,我们可以将其封装成服务,这里就不过多介绍了,大家可以移步这里:http://www.jb51.net/article/43328.htm

  • 相关阅读:
    关于nginx稳定版1.20.1 4层负载 stream模块失效
    Docker 容器内分析 java程序占用 cpu 高问题排查分析
    分组排序查第一第二的差值
    【album】语音合成技术
    8.juery
    7.dom
    6.对象
    5.函数
    4.数组
    3.JS
  • 原文地址:https://www.cnblogs.com/jasondan/p/4108263.html
Copyright © 2011-2022 走看看