Ich verwende CasperJS, um eine Reihe von Klicks, ausgefüllten Formularen, Parsing-Daten usw. über eine Website zu automatisieren.
Casper scheint in einer Liste voreingestellter Schritte in Form von then
Anweisungen organisiert zu sein (siehe Beispiel hier: http://casperjs.org/quickstart.html ), aber es ist unklar, was die nächste Anweisung tatsächlich auslöst.
then
Warten Sie beispielsweise, bis alle ausstehenden Anforderungen abgeschlossen sind? Zählt dies injectJS
als ausstehende Anfrage? Was passiert, wenn ich eine then
Anweisung verschachtelt habe - verkettet an das Ende einer open
Anweisung?
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
});
Ich suche nach einer technischen Erklärung, wie der Fluss in CasperJS funktioniert. Mein spezifisches Problem ist, dass meine letzte then
Aussage (oben) vor meiner casper.open
Aussage läuft und ich nicht weiß warum.
quelle
flow
von casperjs, aber ich habe festgestellt, dass Sie casper im Grunde nicht innerhalb einesevaluate
Anrufs referenzieren können . (dh Sie können keine neue URL, kein neues Protokoll, kein neues Echo usw. öffnen). In meinem Fall wurde also evalu aufgerufen, aber es gab keine Möglichkeit, mit der Außenwelt zu interagieren.evaluate()
ist für Code, der im "Browser" ausgeführt wird, im DOM der Seite, die phantomjs durchsucht. Es gibt also keinecasper.open
, aber es könnte jQuery geben. Ihr Beispiel macht also keinen Sinn, aber ich frage mich immer noch, wasthen()
tatsächlich funktioniert.Antworten:
then()
fügt im Grunde einen neuen Navigationsschritt in einen Stapel ein. Ein Schritt ist eine Javascript-Funktion, die zwei verschiedene Dinge tun kann:Nehmen wir ein einfaches Navigationsszenario:
Sie können alle erstellten Schritte innerhalb des Stapels wie folgt ausdrucken:
Das gibt:
Beachten Sie die
_step()
Funktion, die von CasperJS automatisch hinzugefügt wurde, um die URL für uns zu laden. Wenn die URL geladen wird, wird der nächste im Stapel verfügbare Schrittstep3()
aufgerufen.Wenn Sie Ihre Navigationsschritte definiert haben, führen Sie
run()
sie nacheinander aus:Fußnote: Das Callback / Listener-Zeug ist eine Implementierung des Promise-Musters .
quelle
then()
registriert lediglich eine Reihe von Schritten.run()
und seine Familie von Runner-Funktionen, Rückrufen und Listenern ist alles, was die Arbeit zur Ausführung jedes Schritts tatsächlich erledigt.Jedes Mal , wenn ein Schritt abgeschlossen ist, wird CasperJS überprüfen gegen 3 - Flags:
pendingWait
,loadInProgress
, undnavigationRequested
. Wenn eines dieser Flags wahr ist, tun Sie nichts und gehen Sie bis zu einem späteren Zeitpunkt in den Leerlauf (setInterval
Stil). Wenn keines dieser Flags wahr ist, wird der nächste Schritt ausgeführt.Ab CasperJS 1.0.0-RC4 liegt ein Fehler vor, bei dem unter bestimmten zeitbasierten Umständen die Methode "Nächsten Schritt versuchen" ausgelöst wird, bevor CasperJS Zeit hatte, eines der Flags
loadInProgress
oder eines dernavigationRequested
Flags zu setzen. Die Lösung besteht darin, eines dieser Flags zu hissen, bevor Sie einen Schritt verlassen, in dem diese Flags voraussichtlich gehisst werden (z. B. ein Flag entweder vor oder nach dem Anfordern einescasper.click()
), wie folgt:(Hinweis: Dies ist nur zur Veranschaulichung, eher wie Pseudocode als wie die richtige CasperJS-Form ...)
Um diese Lösung in einer einzigen Codezeile zusammenzufassen, habe ich
blockStep()
diese Github- Pull-Anforderung erweitert , erweitertclick()
undclickLabel()
als Mittel, um sicherzustellen , dass wir das erwartete Verhalten bei der Verwendung erhaltenthen()
. Weitere Informationen, Verwendungsmuster und Mindesttestdateien finden Sie in der Anfrage.quelle
blockStep
, IMHOGemäß der CasperJS-Dokumentation :
then()
Unterschrift:
then(Function then)
Hinter den Kulissen wird der Quellcode für
Casper.prototype.then
unten gezeigt:Erläuterung:
Mit anderen Worten,
then()
plant den nächsten Schritt im Navigationsprozess.Beim
then()
Aufruf wird eine Funktion als Parameter übergeben, die als Schritt aufgerufen werden soll.Es wird überprüft, ob eine Instanz gestartet wurde, und wenn dies nicht der Fall ist, wird der folgende Fehler angezeigt:
Als nächstes wird geprüft, ob das
page
Objekt istnull
.Wenn die Bedingung erfüllt ist, erstellt Casper ein neues
page
Objekt.Danach wird
then()
überprüft diestep
Parameter zu überprüfen , ob es nicht eine Funktion ist.Wenn der Parameter keine Funktion ist, wird der folgende Fehler angezeigt:
Anschließend prüft die Funktion, ob Casper ausgeführt wird.
Wenn Casper nicht ausgeführt wird,
then()
wird der Schritt an das Ende der Warteschlange angehängt.Andernfalls fügt Casper, wenn es ausgeführt wird, einen Teilschritt ein, der eine Ebene tiefer als der vorherige Schritt ist.
Schließlich gibt die
then()
Funktion einstep.added
Ereignis aus und gibt das Casper-Objekt zurück.quelle