【问题标题】:PhantomJS is not executing JSPhantomJS 没有执行 JS
【发布时间】:2015-01-18 15:51:18
【问题描述】:

我尝试使用 PhantomJS 制作 www.fallswoodsmith.com 的屏幕截图。我的代码是:

var page = require('webpage').create();
page.viewportSize = { width: 1024, height: 768 };
page.clipRect = {top: 0, left: 0, width: 1024, height: 768};

page.open('http://www.fallswoodsmith.com', function () {
    page.render('cache/www.fallswoodsmith.com123567266_1024_768.png', {format: 'png', quality: '10'});
    phantom.exit();
});

这个页面只有 JS,所以没有 JS 就没有内容。由于某种原因,PhantomJS 没有执行这个 JS。我还尝试为page.render()phantom.exit() 设置5 秒的超时时间,但这并没有改变什么。如果我在page.render() 之前执行console.log(page.content),我将获得页面的完整HTML - 只是没有JS 所做的更改。

为什么PhantomJS不执行页面的JS?

更新 1: 我添加了以下调试内容:

page.onConsoleMessage = function(msg, lineNum, sourceId) {
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};

page.onError = function(msg, trace) {

    var msgStack = ['ERROR: ' + msg];

    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
        });
    }

    console.error(msgStack.join('\n'));

};

page.onResourceError = function(resourceError) {
    console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
    console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};

page.onResourceTimeout = function(request) {
    console.log('Response (#' + request.id + '): ' + JSON.stringify(request));
};

我的控制台中没有 console.log() 输出...

【问题讨论】:

标签: javascript phantomjs


【解决方案1】:

如果我可以礼貌地问一下,这个网站是谁创建的?我强烈建议不要以 100% 依赖 JavaScript 的方式构建网站。关闭 JavaScript 并“加载”该站点 (www.fallswoodsmith.com) 不会产生任何结果。压缩。纳达。齐尔奇。 </rant>

您正在寻找的答案

运行上面的截图脚本,我得到以下输出:

TypeError: 'undefined' is not a function (evaluating 'joinURL.bind(null, staticServerUrl)')

  http://static.parastorage.com/services/santa-versions/1.150.0/main-r.js:353 in wixRenderSite

要解决该问题,您可以在创建网页对象之后但在加载 URL 之前(即 onInitialized)填充 Function.prototype.bind(PhantomJS 1.x 中缺少 as per this issue)。

结果:

var page = require('webpage').create();

page.onInitialized = function () {
    page.evaluate(function () {
        var isFunction = function (obj) {
            return typeof obj == 'function' || false;
        };
        var slice = Array.prototype.slice;
        Function.prototype.bind = function bind(obj) {
            var args = slice.call(arguments, 1);
            var self = this;
            var F = function () {};
            var bounded = function() {
                return self.apply(
                    this instanceof F ? this : (obj || {}),
                    args.concat(slice.call(arguments))
                );
            };
            F.prototype = this.prototype || {};
            bounded.prototype = new F();
            return bounded;
        };
    });
};

page.open('http://www.fallswoodsmith.com', function () {
    setTimeout(function screenshot() {
        page.render('WORKS.png', {
            format: 'png',
            quality: '10',
        });
        phantom.exit();
    }, 10 * 1000);
});

为什么要等 10 秒才能截屏?好吧,由于该站点完全依赖于 JS,因此没有明显的事件(我能想到的)等待表明页面的加载。你的旅费可能会改变。根据需要增加或减少超时时间。

注意:上面的输出文件名是WORKS.png

PhantomJS 版本

上面的例子已经过测试,可以在 PhantomJS 1.9.7 上运行。该脚本似乎也适用于 PhantomJS 1.9.8,但 1.9.8 有 this issue (Unsafe JavaScript attempt to access frame in 1.9.8),虽然已修复,但它不是任何版本的一部分,并导致以下看起来错误的输出:

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.

视口大小

默认情况下,渲染的图像将是一个完整的页面截图。要修复视口大小,您可以在脚本顶部添加以下内容:

page.viewportSize = {
    width: 1024,
    height: 768
};
page.clipRect = {
    top: 0,
    left: 0,
    width: 1024,
    height: 768
};

Polyfilling .bind

MDN 上找到的 polyfill,如果不进行一些修改,似乎无法正常工作,但是结合 underscore.js 源代码和this answer 会产生上述结果。

【讨论】:

  • 我不知道这个页面的所有者。但它是用 wix.com 制作的,我认为所有页面都是这样构建的。我完全同意这……不是最好的方法。
【解决方案2】:

自 2.1 版以来,phantomjs 已将 polyfill 包含在发行版的 javascript 引擎中。试试他们的latest version

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-13
    • 2017-08-15
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 2013-12-10
    相关资源
    最近更新 更多