使用 page.evaluate 传递参数

IT技术 javascript phantomjs
2021-01-13 21:00:32

我正在使用 PhantomJS page.evaluate() 进行一些抓取。我的问题是我传递给 webkit 页面的代码是沙盒的,因此无法访问我的主要幻影脚本的变量。这使得很难使抓取代码通用。

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

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

如何将参数推送到页面中?

6个回答

我遇到了那个确切的问题。它可以用一点技巧来完成,因为它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);
}
有关为什么会发生这种情况的深入解释,请查看以下问题:stackoverflow.com/questions/12222856/...
2021-03-13 21:00:32
杰出的!这个源代码清楚地解释了它是如何工作的。
2021-03-21 21:00:32
您的解决方案似乎不错,但是如果我想通过回调怎么办,这可能吗?两天去垃圾。JS 回调中是否有像参数这样的全局对象?
2021-04-04 21:00:32

更改已推送,现在您可以将其用作

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

对于那些想要传递多个参数的人,您是否尝试过使用数组作为单个参数?
2021-03-20 21:00:32
如果您传递的对象并不复杂,例如函数等,这是最好的方法。
2021-03-31 21:00:32
你能提供一个传递多个参数的例子吗?
2021-04-03 21:00:32

您可以将参数传递给函数作为 page.evaluate 的参数。

例子:

page.evaluate(function(arg1, arg2){
    console.log(arg1); //Will print "hi"
    console.log(arg2); //Will print "there"
}, "hi", "there");

有一个适用于 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
这可能不是直接用于 PhantomJS,而是 node.js 和 PhantomJS 之间的桥梁。此类桥使用略有不同的语法。
2021-03-15 21:00:32
如果您尝试将参数传递到phantomjs-nodejs bridge 中的沙盒评估方法,则此答案是票证文档还很新鲜。我几乎放弃了,直到我找到了这个答案。谢谢!
2021-03-15 21:00:32

另一种可能性:通过 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 + ')');       
    )}
});
在 PhantomJS 中不起作用,因为它page.evaluate()是沙盒的。
2021-03-25 21:00:32