2012-03-23 87 views
48

我正在使用PhantomJS page.evaluate()做一些刮擦。我的問題是,我傳遞給webkit頁面的代碼是沙盒,因此無法訪問我的主幻像腳本的變量。這使得拼寫代碼變得很難。通過頁面傳遞參數.evaluate

page.open(url, function() { 
    var foo = 42; 

    page.evaluate(function() { 
    // this code has no access to foo 
    console.log(foo); 
    }); 
} 

如何將參數推入頁面?

+2

我相信你會發現這個答案更充分:http://stackoverflow.com/questions/28524130/phantomjs -does-not-arguments-to-function-passed-to-page-evaluation – user2977636 2016-08-19 02:54:43

回答

62

我有這個確切的問題。它可以用一點小手段完成,因爲page.evaluate也可以接受一個字符串。

有幾種方法可以做到這一點,但我使用了一個名爲evaluate的包裝,它接受附加參數傳遞給必須在webkit端進行評估的函數。你會使用這樣的:

page.open(url, function() { 
    var foo = 42; 

    evaluate(page, function(foo) { 
    // this code has now has access to foo 
    console.log(foo); 
    }, foo); 
}); 

這裏是evaluate()功能:

/* 
* This function wraps WebPage.evaluate, and offers the possibility to pass 
* parameters into the webpage function. The PhantomJS issue is here: 
* 
* http://code.google.com/p/phantomjs/issues/detail?id=132 
* 
* This is from comment #43. 
*/ 
function evaluate(page, func) { 
    var args = [].slice.call(arguments, 2); 
    var fn = "function() { return (" + func.toString() + ").apply(this, " + JSON.stringify(args) + ");}"; 
    return page.evaluate(fn); 
} 
+0

太棒了!該源代碼清楚地解釋了它的工作原理。 – Light 2015-12-23 03:58:01

+1

關於爲什麼發生這種情況的深入解釋,看看這個問題:http://stackoverflow.com/questions/12222856/passing-arguments-to-anonymous-function-inside-page-includejs-and-page-評估 – 2016-02-29 15:30:10

+0

你的解決方案似乎很好,但如果我想通過回調,可能嗎?兩天去了垃圾。在JS回調全局對象像參數? – Velaro 2017-07-13 14:10:16

2

另一種可能性:通過變量與URL。例如,通過對象x

// turn your object "x" into a JSON string 
var x_json = JSON.stringify(x); 

// add to existing url 
// you might want to check for existing "?" and add with "&" 
url += '?' + encodeURIComponent(x_json); 

page.open(url, function(status){ 
    page.evaluate(function(){ 
     // retrieve your var from document URL - if added with "&" this needs to change 
     var x_json = decodeURIComponent(window.location.search.substring(1)); 
     // evil or not - eval is handy here 
     var x = eval('(' + x_json + ')');  
    )} 
}); 
+0

在PhantomJS中不起作用,因爲'page.evaluate()'是沙盒。 – 2015-07-16 11:47:53

60

的變化一直推,現在你可以使用它作爲

page.open(url, function() { 
    var foo = 42; 

    page.evaluate(function(foo) { 
    // this code has now has access to foo 
    console.log(foo); 
    }, foo); 
} 

推詳情請看這裏:https://github.com/ariya/phantomjs/commit/81794f9096

+0

這是最好的方式來做到這一點,如果你通過的對象並不複雜,就像一個函數等。 – Nik 2012-12-28 23:12:46

+5

你能提供一個傳遞多個參數的例子嗎? – cwd 2014-10-26 18:56:44

+0

對於那些想傳遞多個參數的人,你是否嘗試過使用數組作爲單個參數? – bla 2017-07-27 10:27:43

0

這個工作對我來說:

page.evaluate("function() {document.body.innerHTML = '" + size + uid + "'}"); 

意味着把所有東西都作爲一個字符串。無論如何,它成爲一個字符串。檢查庫源。

2

存在與PhantomJS 0.9.2和0.2.0工程解決方案:

page.evaluate(
    function (aa, bb) { document.title = aa + "/" + bb;}, //the function 
    function (result) {}, // a callback when it's done 
    "aaa", //attr 1 
    "bbb"); //attr 2 
+1

這可能不是直接用於PhantomJS,而是node.js和PhantomJS之間的橋樑。這樣的橋使用稍微不同的語法。 – 2015-07-16 11:48:35

+1

如果您嘗試將參數傳遞到[phantomjs-nodejs bridge](https://github.com/sgentle/phantomjs-node)中的沙盒評估方法,則此答案爲票證。文檔仍然新鮮。我幾乎放棄了,直到我找到了答案。謝謝! – DMfll 2016-01-19 10:33:48

0

你就不能綁定參數傳遞給函數?

page.evaluate.bind(args)(callbackFn) 
0

雖然您可以將參數傳遞到evaluate(function, arg1, arg2, ...),但這通常有點麻煩。特別是在傳遞多個變量的情況下,或更糟糕的是,功能。

爲了解決這個障礙,可以使用injectJs(filename)代替。

page.open(url, function() { 
    if (webpage.injectJs('my_extra_functionality.js')) { 
     page.evaluate(function() { 
      // this code has access to foo and also myFunction(); 
      console.log(foo); 
      console.log(myFunction()); 
     }); 
    } 
    else { 
     console.log("Failed to inject JS"); 
    } 
} 

my_extra_functionality.js是在同一個目錄中的本地文件:

var foo = 42; 
var myFunction = function(){ 
    return "Hello world!"; 
}