2016-03-07 92 views
0

以及我的代码是这样短短的几行phantomjs不渲染网页为PNG

var a = "http://lnmtl.com/chapter/renegade-immortal-chapter-"; 
var b = 558; 
var d = "rennegrade_ch"; 
var f = ".png"; 
var page = require('webpage').create(); 
var i = 0; 
for (i = b; i < 560; i++) { 
    var c = a + i; 
    console.log(c); 
    page.open(c, function() { 
     var e = d + i + f; 
     console.log(e); 
     page.render(e); 

    }); 
} 
phantom.exit(); 

网页可以单独渲染,但一旦我把它里面的for循环它是所有打印第一控制台输出正确,但第二个它跳过我猜它没有进入page.open函数然后为循环值增加然后同样的事情再次发生我不知道为什么它没有进入渲染功能我试图把var page = require('网页') 。创建(); inside for loop too但仍然没有变化

更新:在另一个问题stackoverflow.com/questions/31621577/png-is-not-being-rendered-using-phantomjs-with-multiple-attempts-in-a-循环?rq = 1 有人指出,这种方法不会工作,因为功能的异步性质,但其中提供的示例代码是不够有用任何人的例子,我也试过设置超时,因为它仍然是同样的事情发生,所以任何其他想法?

+0

到底是什么问题,在[我的回答(http://stackoverflow.com/a/31625166/1816580)上的链接的问题所提供的解决方案?您的代码显示我描述的问题2和3。 –

+0

啊对不起,递归部分和状态变量困惑我那里我的错误,但你可以举例设置超时我试过,但它没有工作 –

回答

0

对于内环路异步请求,你应该使用异步库,以便您可以调试代码并没有得到内存泄漏问题

async-js会在你的情况良好

npm install async

var async = require('async'); 
var a = "http://lnmtl.com/chapter/renegade-immortal-chapter-"; 
var b = 558; 
var d = "rennegrade_ch"; 
var f = ".png"; 
var page = require('webpage').create(); 
var i = 0; 
async.whilst(
    function() { 
    return i < 560; 
    }, 
    function(callback) { 
    i++; 
    var c = a + i; 
    console.log(c); 
    page.open(c, function() { 
     var e = d + i + f; 
     console.log(e); 
     page.render(e); 
     callback(null, i); 
    }); 
    }, 
    function(err, n) { 
    if(err) console.log(err); 
    phantom.exit(); 
    }); 
1

在进行任何渲染之前,您的phantom.exit()调用会终止PhantomJS浏览器。您必须等待渲染结束,然后才可以exit()。您需要有一些机制来说明何时完成渲染。我建议将每个渲染包装在Promise中。然后使用Promise.all()等待所有渲染承诺解决。解决后,退出PhantomJS。


现在,你有下面是什么,不尊重的page.open()异步特性:

for (...) { 
    // I probably wont finish because phantom dies almost immediately 
    page.open(c, function() { 
     // I won't finish running since phantom dies 
     page.render(e); 
    }); 
} 
// I'm going to kill the phantom almost immediately 
phantom.exit(); 

你想要的东西,像下面的代码,这将等待所有的渲染完成。这会将我们提供的每个站点渲染到子目录“呈现”中。

注意:您将需要安装es6-promise垫片才能工作,因为PhantomJS尚不支持Promises。感谢the comment有关Artjon B

/*jslint node:true*/ 
/*globals phantom, sayHello*/ 

"use strict"; 

var Promise = require("es6-Promise").Promise; 

// Array of URLs that we want to render 
var urlArr = [ 
    { 
     name: "google", 
     url: "http://www.google.com" 
    }, 
    { 
     name: "yahoo", 
     url: "http://www.yahoo.com" 
    }, 
    { 
     name: "bing", 
     url: "http://www.bing.com" 
    } 
]; 

// Map URLs to promises 
var proms = urlArr.map(function (url) { 
    // Return a promise for each URL 
    return new Promise(function (resolve, reject) { 
     // Make a page 
     var page = require("webpage").create(); 
     // Open the URL 
     console.log("opening: " + url.name); 
     page.open(url.url, function() { 
      // Render the page 
      page.render("render/" + url.name + ".png"); 
      console.log("done rendering: " + url.name); 
      // Say that we are done with rendering 
      resolve(); 
     }); 
    }); 
}); 

// Wait for all rendering to finish 
Promise.all(proms).then(function() { 
    console.log("closing phantom"); 
    // Exit phantom 
    phantom.exit(); 
}); 
+1

PhantomJS不支持承诺(PhantomJS 2.1.1和1.9.8测试)。你需要一个垫片。 –

+0

@ArtjomB。谢谢,Artjom,更正了使用es6-promise垫片的代码。这适用于我的客户。 – zero298