На PhantomJS я не могу включить jQuery и без jQuery я не могу публиковать данные формы
У меня проблемы с запуском jQuery в PhantomJS. Я нашел этот ответ, который говорит о том, что внутри функции оценки нет никакой переменной, но вопрос о модуле узла, и в моем примере я вызываю только console.log
внутри оценить функцию. Я также поставил этот вопрос на GitHub.
Ранее для некоторых страниц evaluate
код не выполнен Теперь, когда @b1f56gd4 предоставил некоторую помощь, теперь он печатает сообщения; Я не могу выполнить это, но теперь я вижу это:
На странице https://login.yahoo.com/ размещался небезопасный контент с http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js.
Я не могу загрузить jQuery из другого домена и --local-to-remote-url-access=true
или же --web-security=false
варианты не имеют значения.
Я постараюсь загрузить JQuery локально. Вот код:
console.log('Loading a web page');
var url = 'https://login.yahoo.com/';
var page = require('webpage').create();
console.log('Setting error handling');
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
})
phantom.exit();
}
console.log('Error handling is set');
console.log('Opening page');
page.open(url, function (status) {
if (status != 'success') {
console.log('F-' + status);
} else {
console.log('S-' + status);
//-------------------------------------------------
var jsLoc = '';
jsLoc = 'jquery.min.js'; // to load local
//jsLoc = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; // to load remote
var func = function(pg){
console.log('Function called');
console.log('Page evaluating');
console.log(pg);
pg.evaluate(function() {
console.log('Page evaluate started');
//---
var loginVar = 'ih5d4hf65465fd45h6@yahoo.com.br';
var pwdVar = 'itsmypass_445f4hd564hd56f46s';
//---
$("#login_form #username").value = loginVar;
$("#login_form #passwd").value = pwdVar;
//---
});
console.log('Rendering');
pg.render('ystsA.png');
console.log('Rendered');
}
if (typeof jQuery == 'undefined') {
console.log('JQuery Loading'); // <<<<==== Execute only until here
console.log('Source:['+jsLoc+']');
var rs = page.includeJs(jsLoc, function() // <<<<===== Fail here, jsLoc was changed to load locally and after tried remotely, i tried use page.injectJs but fail too
{
console.log('JQuery Loaded'); // <<<< ===== Never reach here, no matter if loading local or remote script in include above
func(page);
});
page.render('ystsB.png');
} else {
console.log('JQuery Already Loaded');
func(page);
page.render('ystsC.png');
}
//-------------------------------------------------
}
phantom.exit();
});
Прочитав ответ @g4d564w56, я сделал все без JQuery, затем я могу заполнить текстовое поле, но не могу нажать на кнопку, чтобы опубликовать форму входа в систему.
Смотрите новый код:
console.log('Loading a web page');
var url = 'https://login.yahoo.com/';
var page = require('webpage').create();
console.log('Setting error handling');
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
})
phantom.exit();
}
console.log('Error handling is set');
console.log('Opening page');
page.open(url, function (status) {
if (status != 'success') {
console.log('F-' + status);
} else {
console.log('S-' + status);
//-------------------------------------------------
var jsLoc = '';
jsLoc = 'jquery.min.js'; // to load local
//jsLoc = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; // to load remote
var act01 = function(pg){
console.log('Function called');
console.log('Page evaluating');
console.log(pg);
pg.evaluate(function() {
var getElmById = function(id){
return document.getElementById(id);
}
console.log('Page evaluate started');
//---
var loginVar = 'ih5d4hf65465fd45h6@yahoo.com.br';
var pwdVar = 'itsmypass_445f4hd564hd56f46s';
//---
getElmById("username").value = loginVar;
getElmById("passwd").value = pwdVar;
getElmById("login_form").submit(); /// <<<<==== now its dont work !!!
//---
});
console.log('Rendering');
pg.render('ystsA.png');
console.log('Rendered');
}
act01(page);
//-------------------------------------------------
}
phantom.exit();
});
5 ответов
Я знаю, что на этот вопрос уже отвечали около года назад, но ответ на самом деле не решал проблему. Причина ошибки ниже:
"На странице https://login.yahoo.com/ размещался небезопасный контент с http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js."
Является ли эта страница входа страницей https, и вы пытаетесь загрузить ресурс http. Если вы измените URL-адрес на https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js эта ошибка исчезнет. Потребовалось время, чтобы понять это.
Рабочая версия с использованием поиска Google.
var page, doSearch, displayResults;
page = require('webpage').create();
doSearch = function() {
console.log('Searching...');
page.evaluate(function() {
$("input[name=q]").val('what is phantomjs');
$("form").trigger('submit');
return true;
});
page.render('phantomjs-searching.png');
};
displayResults = function() {
console.log('Results...');
page.evaluate(function() {
$('h3 a').each(function(i) {
console.log([i + 1, $(this).text(), ' // ' + $(this).attr('href')].join(': '));
});
return true;
});
page.render('phantomjs-results.png');
};
page.onLoadFinished = function(status) {
if (status === 'success') {
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js', function() {
if (!phantom.state) {
doSearch();
phantom.state = 'results';
} else {
displayResults();
phantom.exit();
}
});
} else {
console.log('Connection failed.');
phantom.exit();
}
};
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.open('http://google.com');
Попробуйте следующий код из http://snippets.aktagon.com/snippets/534-How-to-scrape-web-pages-with-PhantomJS-and-jQuery. Он загружает локальную копию jQuery, но также может использовать экземпляр jQuery, загруженный запрошенной страницей.
var page = new WebPage(),
url = 'http://localhost/a-search-form',
stepIndex = 0;
/**
* From PhantomJS documentation:
* This callback is invoked when there is a JavaScript console. The callback may accept up to three arguments:
* the string for the message, the line number, and the source identifier.
*/
page.onConsoleMessage = function (msg, line, source) {
console.log('console> ' + msg);
};
/**
* From PhantomJS documentation:
* This callback is invoked when there is a JavaScript alert. The only argument passed to the callback is the string for the message.
*/
page.onAlert = function (msg) {
console.log('alert!!> ' + msg);
};
// Callback is executed each time a page is loaded...
page.open(url, function (status) {
if (status === 'success') {
// State is initially empty. State is persisted between page loads and can be used for identifying which page we're on.
console.log('============================================');
console.log('Step "' + stepIndex + '"');
console.log('============================================');
// Inject jQuery for scraping (you need to save jquery-1.6.1.min.js in the same folder as this file)
page.injectJs('jquery-1.6.1.min.js');
// Our "event loop"
if(!phantom.state){
initialize();
} else {
phantom.state();
}
// Save screenshot for debugging purposes
page.render("step" + stepIndex++ + ".png");
}
});
// Step 1
function initialize() {
page.evaluate(function() {
$('form#search input.query').val('Jebus saves');
$('form#search').submit();
console.log('Searching...');
});
// Phantom state doesn't change between page reloads
// We use the state to store the search result handler, ie. the next step
phantom.state = parseResults;
}
// Step 2
function parseResults() {
page.evaluate(function() {
$('#search-result a').each(function(index, link) {
console.log($(link).attr('href'));
})
console.log('Parsed results');
});
// If there was a 3rd step we could point to another function
// but we would have to reload the page for the callback to be called again
phantom.exit();
}
Существует хорошо известная ошибка, что PhantomJS не может загрузить JQuery, будет сложно отправить некоторые данные формы на сервер, но вы можете выбрать элементы только с использованием querySelector. Все как в этом примере: как очистить ссылки с phantomjs
Ответ @lmeurs очень хорош, но не функционален.
Я использовал ответ, чтобы создать что-то функциональное для вас:) .
var page = new WebPage();
var url = 'http://br.search.yahoo.com';
var stepIndex = 0;
page.onConsoleMessage = function (msg, line, source) { console.log('console> ' + msg); };
page.onAlert = function (msg) { console.log('alert!!> ' + msg); };
function takeShot(){
console.log("TakingShot");
page.render("step" + stepIndex + ".png");
console.log("ShotTake");
}
function step0() {
console.log("step 00 enter");
page.evaluate(function() {
$("form [type='text']").val('its now sunday searching it');
$("form [type='submit']").submit();
});
console.log("step 00 exit");
}
function step1() {
console.log("step 01 enter");
page.evaluate(function() {
$('#search-result a').each(function(index, link) {
console.log($(link).attr('href'));
})
});
console.log("step 01 exit");
phantom.exit();
}
page.open(url, function (status) {
console.log("[- STARTING -]");
if (status === 'success') {
var cmd = ""
page.injectJs('jquery-1.6.1.min.js');
while(true)
{
console.log("Step["+stepIndex+"] starting on ["+new Date()+"]");
//cmd = "var x = step"+stepIndex+";"
//console.log(cmd);
//eval(cmd);
switch(stepIndex){
case 0:
step0();
break;
case 1:
step1();
break;
}
takeShot();
stepIndex++;
}
}
});