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,
      width:  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,
            width:  bb.width,
            height: bb.height
          };
          // 预留一定的渲染时间
          window.setTimeout(function () {
            page.render(output);
            page.close();
            console.log('render ok');
         phantom.exit(); }
    , 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

  • 相关阅读:
    NTP on FreeBSD 12.1
    Set proxy server on FreeBSD 12.1
    win32 disk imager使用后u盘容量恢复
    How to install Google Chrome Browser on Kali Linux
    Set NTP Service and timezone on Kali Linux
    Set static IP address and DNS on FreeBSD
    github博客标题显示不了可能是标题包含 特殊符号比如 : (冒号)
    server certificate verification failed. CAfile: none CRLfile: none
    删除文件和目录(彻底的)
    如何在Curl中使用Socks5代理
  • 原文地址:https://www.cnblogs.com/tdalcn/p/9254522.html
Copyright © 2011-2022 走看看