Phantomjs не выполняет функцию в функции page.evaluate
Я очищаю страницу Facebook модулем узла PhantomJS ( https://github.com/sgentle/phantomjs-node), но когда я пытаюсь оценить страницу, она не оценивает функцию, которую я ей передаю. Выполнение его в автономном скрипте и запуск с интерпретатором Node работает.. Тот же код в приложении Express.js не работает.
Это мой код
facebookScraper.prototype.scrapeFeed = function (url, cb) {
f = ':scrapeFeed:';
var evaluator = function (s) {
var posts = [];
for (var i = 0; i < FEED_ITEMS; i++) {
log.info(__filename+f+' iterating step ' + i);
log.info(__filename+f+util.inspect(document, false, null));
}
return {
news: posts
};
}
phantom.create(function (ph) {
ph.createPage(function (page) {
log.fine(__filename+f+' opening url ' + url);
page.open(url, function (status) {
log.fine(__filename+f+' opened site? ' + status);
setTimeout(function() {
page.evaluate(evaluator, function (result) {
log.info(__filename+f+'Scraped feed: ' + util.inspect(result, false, null));
cb(result, ph);
});
}, 5000);
});
});
});
};
На выходе я получаю:
{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opening url <URL> ","timestamp":"2012-09-23T18:35:10.151Z"}
{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opened site? success","timestamp":"2012-09-23T18:35:12.682Z"}
{"level":"info","message":"PATH/fb_regular.js:scrapeFeed: Scraped feed: null","timestamp":"2012-09-23T18:35:12.687Z"}
Итак, как вы видите, он вызывает функцию фантомного обратного вызова (второй параметр в функции оценки) с нулевым аргументом, но не выполняет первый параметр (моя функция оценки, которая печатает итерацию шага X).
Кто-нибудь знает в чем проблема?
5 ответов
Я не уверен относительно того, какую версию PhantomJS вы используете, но что касается документации по версиям 1.6+, регистрация внутри оцененного скрипта запишет результат на содержащейся странице. Он не будет входить в вашу консоль. Чтобы получить это, вам нужно привязать ведение журнала к событию onConsoleMessage страниц:
page.onConsoleMessage = function (msg) { console.log(msg); };
Что касается недоступности результата: функция page.evaluate принимает аргументы примерно так: сначала выполняется функция, а остальные передаются в качестве входных данных для этой функции. Результат возвращается напрямую:
var title = page.evaluate(function (s) {
return document.querySelector(s).innerText;
}, 'title');
console.log(title);
evaluate
выполняется в режиме песочницы, что означает, что ни одна из переменных, определенных в содержащей среде, не доступна, включая cb
или даже phantom
объект или любые функции, которые вы могли определить.
Вы можете явно направить информацию в песочницу в качестве дополнительных аргументов evaluate
,
page.evaluate(function(cb){...}, cb);
PhantomJS" page.evaluate()
Функция - это дверь в контекст DOM (контекст страницы). Доступ к DOM возможен только через эту функцию. Поскольку функция является изолированной, вы не можете использовать переменные, определенные вне ее, и они должны быть переданы явно. Существуют ограничения на то, что можно передавать и выводить ( документы):
Примечание. Аргументы и возвращаемое значение
evaluate
Функция должна быть простым примитивным объектом. Эмпирическое правило: если его можно сериализовать через JSON, то это нормально.Замыкания, функции, DOM-узлы и т. Д. Не будут работать!
phantomjs-node является мостом между PhantomJS и node.js и поэтому имеет немного иной API, чем сам PhantomJS. Синхронные функции в PhantomJS не возвращают ничего в phantomjs-node, но принимают обратный вызов в том месте, где передан результат. Обратный вызов выполняется во внешнем контексте и не помещается в песочницу.
Аргументы могут быть переданы следующим образом:
page.evaluate(function(arg1, arg2){
// use arg1 and arg2 in the page
// return `result`
}, function(result){
// use `result` in the node context
}, "some arg1", "another arg");
Следующее сработало для меня, чтобы оценить страницу:
page.evaluate(function(s) {
return document.querySelector(s)
}, 'body').then(res => {
console.log(res)
})
Есть кто-то, у кого есть блок оценки с единственной строкой console.log внутри, и он никогда не выполняется, это не всегда проблема песочницы.
см. ссылку: на PhantomJS я не могу включить jQuery и без jQuery я не могу публиковать данные формы