J'essaie d'utiliser phantomJS (quel outil génial!) Pour soumettre un formulaire pour une page pour laquelle j'ai des informations de connexion, puis pour exporter le contenu de la page de destination sur stdout. Je peux accéder au formulaire et définir ses valeurs avec succès en utilisant fantôme, mais je ne suis pas tout à fait sûr de la syntaxe correcte pour soumettre le formulaire et afficher le contenu de la page suivante. Ce que j'ai jusqu'ici c'est:
var page = new WebPage();
var url = phantom.args[0];
page.open(url, function (status) {
if (status !== 'success') {
console.log('Unable to access network');
} else {
console.log(page.evaluate(function () {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].elements["email"].value="[email protected]";
arr[i].elements["password"].value="mypassword";
// This part doesn't seem to work. It returns the content
// of the current page, not the content of the page after
// the submit has been executed. Am I correctly instrumenting
// the submit in Phantom?
arr[i].submit();
return document.querySelectorAll('html')[0].outerHTML;
}
}
return "failed :-(";
}));
}
phantom.exit();
}
Je l'ai compris. Fondamentalement, c'est une question asynchrone. Vous ne pouvez pas simplement soumettre et vous attendre à rendre immédiatement la page suivante. Vous devez attendre que l'événement onLoad de la page suivante soit déclenché. Mon code est ci-dessous:
var page = new WebPage(), testindex = 0, loadInProgress = false;
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started");
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished");
};
var steps = [
function() {
//Load Login Page
page.open("https://website.com/theformpage/");
},
function() {
//Enter Credentials
page.evaluate(function() {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].elements["email"].value="mylogin";
arr[i].elements["password"].value="mypassword";
return;
}
}
});
},
function() {
//Login
page.evaluate(function() {
var arr = document.getElementsByClassName("login-form");
var i;
for (i=0; i < arr.length; i++) {
if (arr[i].getAttribute('method') == "POST") {
arr[i].submit();
return;
}
}
});
},
function() {
// Output content of page to stdout after form has been submitted
page.evaluate(function() {
console.log(document.querySelectorAll('html')[0].outerHTML);
});
}
];
interval = setInterval(function() {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}, 50);
CasperJS fournit également une interface de haut niveau pour la navigation dans PhantomJS, notamment en cliquant sur les liens et en remplissant des formulaires.
Mise à jour pour ajouter article du 28 juillet 2015 comparant PhantomJS et CasperJS .
(Merci au commentateur M. M!)
L'envoi de demandes POST brutes peut s'avérer parfois plus pratique. Ci-dessous, vous pouvez voir exemple original post.js de PhantomJS
// Example using HTTP POST operation
var page = require('webpage').create(),
server = 'http://posttestserver.com/post.php?dump',
data = 'universe=expanding&answer=42';
page.open(server, 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});
Comme il a été mentionné ci-dessus CasperJS est le meilleur outil pour remplir et envoyer des formulaires. Exemple le plus simple possible pour remplir et envoyer un formulaire à l’aide de la fonction fill () :
casper.start("http://example.com/login", function() {
//searches and fills the form with id="loginForm"
this.fill('form#loginForm', {
'login': 'admin',
'password': '12345678'
}, true);
this.evaluate(function(){
//trigger click event on submit button
document.querySelector('input[type="submit"]').click();
});
});