2016-03-07 93 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