Пропустить аргументы с помощью page.evaluate
Я использую PhantomJS page.evaluate(), чтобы сделать некоторые выскабливания. Моя проблема в том, что код, который я передаю на страницу webkit, изолирован и поэтому не имеет доступа к переменным моего основного phantom script. Это затрудняет создание общего кода скремблирования.
page.open(url, function() {
var foo = 42;
page.evaluate(function() {
// this code has no access to foo
console.log(foo);
});
}
Как я могу нажимать аргументы на страницу?
Ответы
Ответ 1
У меня была эта точная проблема. Это можно сделать с небольшим обманом, потому что page.evaluate
также может принимать строку.
Существует несколько способов сделать это, но я использую оболочку с именем evaluate
, которая принимает дополнительные параметры для перехода к функции, которая должна быть оценена на стороне веб-сайта. Вы бы использовали его следующим образом:
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);
}
Ответ 2
Это изменение было нажато, и теперь вы можете использовать его как
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
Ответ 3
Другая возможность: передать переменные в 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 + ')');
)}
});
Ответ 4
Существует решение, которое работает с PhantomJS 0.9.2 и 0.2.0:
page.evaluate(
function (aa, bb) { document.title = aa + "/" + bb;}, //the function
function (result) {}, // a callback when it done
"aaa", //attr 1
"bbb"); //attr 2
Ответ 5
Это работает для меня:
page.evaluate("function() {document.body.innerHTML = '" + size + uid + "'}");
Значит положить все как строку. Так или иначе, это станет строкой. Проверьте источник библиотеки.
Ответ 6
Не можете ли вы просто привязать аргументы к функции?
page.evaluate.bind(args)(callbackFn)
Ответ 7
Пока вы можете передавать аргументы в оценить (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!";
}