J'utilise CasperJS pour automatiser une série de clics, de formulaires complétés, d'analyser des données, etc. via un site Web.
Casper semble être organisé en une liste d'étapes prédéfinies sous la forme d'instructions then
(voir leur exemple ici: http://casperjs.org/quickstart.html ) mais on ignore ce qui déclenche l'exécution de l'instruction suivante .
Par exemple, then
attend-il que toutes les demandes en attente soient terminées? injectJS
compte-t-il comme demande en attente? Que se passe-t-il si une instruction then
est imbriquée - enchaînée à la fin d'une instruction open
?
casper.thenOpen('http://example.com/list', function(){
casper.page.injectJs('/libs/jquery.js');
casper.evaluate(function(){
var id = jQuery("span:contains('"+itemName+"')").closest("tr").find("input:first").val();
casper.open("http://example.com/show/"+id); //what if 'then' was added here?
});
});
casper.then(function(){
//parse the 'show' page
});
Je cherche une explication technique sur le fonctionnement du flux dans CasperJS. Mon problème spécifique est que ma dernière instruction then
(ci-dessus) s'exécute avant mon instruction casper.open
et je ne sais pas pourquoi.
then()
ajoute fondamentalement une nouvelle étape de navigation dans une pile. Une étape est une fonction javascript qui peut faire deux choses différentes:
Prenons un scénario de navigation simple:
var casper = require('casper').create();
casper.start();
casper.then(function step1() {
this.echo('this is step one');
});
casper.then(function step2() {
this.echo('this is step two');
});
casper.thenOpen('http://google.com/', function step3() {
this.echo('this is step 3 (google.com is loaded)');
});
Vous pouvez imprimer toutes les étapes créées dans la pile de la manière suivante:
require('utils').dump(casper.steps.map(function(step) {
return step.toString();
}));
Ça donne:
$ casperjs test-steps.js
[
"function step1() { this.echo('this is step one'); }",
"function step2() { this.echo('this is step two'); }",
"function _step() { this.open(location, settings); }",
"function step3() { this.echo('this is step 3 (google.com is loaded)'); }"
]
Notez la fonction _step()
qui a été ajoutée automatiquement par CasperJS pour charger l’URL pour nous; Lorsque l'URL est chargée, l'étape suivante disponible dans la pile, à savoir step3()
, est appelée.
Lorsque vous avez défini vos étapes de navigation, run()
les exécute une par une de manière séquentielle:
casper.run();
Note de bas de page: le programme callback/listener est une implémentation du modèle Promise .
then()
enregistre simplement une série d'étapes.
run()
et sa famille de fonctions de coureur, de callbacks et d’écouteurs sont tous ce qui fait le travail d’exécution de chaque étape.
Chaque fois qu'une étape est terminée, CasperJS vérifie trois indicateurs: pendingWait
, loadInProgress
et navigationRequested
. Si l'un de ces indicateurs est vrai, ne faites rien, restez inactif jusqu'à une date ultérieure (style setInterval
). Si aucun de ces indicateurs n'est vrai, l'étape suivante sera exécutée.
Depuis CasperJS 1.0.0-RC4, il existe une faille dans laquelle, dans certaines circonstances temporelles, la méthode "essayez de faire la prochaine étape" sera déclenchée avant que CasperJS ait eu le temps de lever l'un des drapeaux loadInProgress
ou navigationRequested
. La solution consiste à lever l'un de ces drapeaux avant de quitter une étape où ces drapeaux sont censés être levés (ex: lever un drapeau soit avant, soit après avoir demandé une casper.click()
), peut-être comme suit:
(Note: Ceci est seulement illustratif, ressemble plus à psuedocode qu'à la forme correcte de CasperJS ...)
step_one = function(){
casper.click(/* something */);
do_whatever_you_want()
casper.click(/* something else */); // Click something else, why not?
more_magic_that_you_like()
here_be_dragons()
// Raise a flag before exiting this "step"
profit()
}
Pour résumer cette solution dans une seule ligne de code, j'ai introduit blockStep()
dans ce github requête d'extraction , en étendant click()
et clickLabel()
afin de garantir que le comportement attendu par then()
est obtenu. Consultez la demande pour plus d'informations, les modèles d'utilisation et les fichiers de test minimum.