Używam CasperJS do automatyzacji serii kliknięć, wypełnionych formularzy, analizowania danych itp. Za pośrednictwem strony internetowej.
Wygląda na to, że Casper jest uporządkowany na liście wstępnie ustawionych kroków w postaci then
instrukcji (zobacz ich przykład tutaj: http://casperjs.org/quickstart.html ), ale nie jest jasne, co powoduje, że następna instrukcja faktycznie działa.
Na przykład, czy then
czeka na zakończenie wszystkich oczekujących żądań? Czy injectJS
liczy się jako oczekujące żądanie? Co się stanie, jeśli mam then
instrukcję zagnieżdżoną - połączoną łańcuchem na końcu open
instrukcji?
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
});
Szukam technicznego wyjaśnienia, jak działa przepływ w CasperJS. Mój specyficzny problem polega na tym, że moje ostatnie then
oświadczenie (powyżej) jest uruchamiane przed moim casper.open
oświadczeniem i nie wiem dlaczego.
źródło
flow
zasad casperjs, ale odkryłem, że w zasadzie nie możesz odwoływać się do caspera z poziomuevaluate
połączenia. (tzn. nie możesz otworzyć nowego adresu URL, dziennika, echa itp.). Tak więc w moim przypadku wywołano ocenę, ale bez możliwości interakcji ze światem zewnętrznym.evaluate()
dotyczy kodu uruchamianego w „przeglądarce”, w modelu DOM strony, którą przegląda phantomjs. Więc nie macasper.open
, ale może istnieć jQuery. Więc twój przykład nie ma sensu, ale wciąż zastanawiam się, cothen()
tak naprawdę działa.Odpowiedzi:
then()
po prostu dodaje nowy krok nawigacji w stosie. Krok to funkcja javascript, która może zrobić dwie różne rzeczy:Weźmy prosty scenariusz nawigacji:
Możesz wydrukować wszystkie utworzone kroki w stosie w następujący sposób:
To daje:
Zwróć uwagę na
_step()
funkcję, która została dodana automatycznie przez CasperJS, aby załadować adres URL dla nas; po załadowaniu adresu URLstep3()
następuje wywołanie kolejnego kroku dostępnego na stosie - którym jest -.Po zdefiniowaniu kroków nawigacji
run()
wykonuje je po kolei:Przypis: funkcja callback / listener jest implementacją wzorca Promise .
źródło
then()
rejestruje jedynie serię kroków.run()
i jego rodzina funkcji uruchamiających, wywołań zwrotnych i słuchaczy jest tym, co faktycznie wykonuje pracę na każdym kroku.Ilekroć krokiem jest zakończona, CasperJS sprawdzi przeciwko 3 flagi:
pendingWait
,loadInProgress
, inavigationRequested
. Jeśli którakolwiek z tych flag jest prawdziwa, nie rób nic, idź bezczynnie do późniejszego czasu (setInterval
styl). Jeśli żadna z tych flag nie jest prawdziwa, zostanie wykonany następny krok.Począwszy od CasperJS 1.0.0-RC4, istnieje błąd, w którym w pewnych okolicznościach zależnych od czasu metoda „spróbuj zrobić następny krok” zostanie wyzwolona, zanim CasperJS zdąży podnieść jedną z flag
loadInProgress
lubnavigationRequested
. Rozwiązaniem jest podniesienie jednej z tych flag przed opuszczeniem jakiegokolwiek kroku, na którym te flagi mają zostać podniesione (np .: podniesienie flagi przed lub po zapytaniu o acasper.click()
), może tak:(Uwaga: to jest tylko ilustracyjne, bardziej jak psuedokod niż właściwy formularz CasperJS ...)
Aby zawrzeć to rozwiązanie w pojedynczym wierszu kodu, wprowadziłem
blockStep()
w tym żądaniu pull z github , rozszerzającclick()
iclickLabel()
jako sposób na zagwarantowanie, że uzyskamy oczekiwane zachowanie podczas używaniathen()
. Sprawdź prośbę o więcej informacji, wzorce użytkowania i minimalną liczbę plików testowych.źródło
blockStep
, IMHOZgodnie z dokumentacją CasperJS :
then()
Podpis:
then(Function then)
Za kulisami poniżej przedstawiono kod źródłowy
Casper.prototype.then
:Wyjaśnienie:
Innymi słowy,
then()
planuje następny krok w procesie nawigacji.Gdy
then()
jest wywoływana, przekazywana jest funkcja jako parametr, który ma zostać wywołany jako krok.Sprawdza, czy wystąpienie zostało uruchomione, a jeśli tak się nie stało, wyświetla następujący błąd:
Następnie sprawdza, czy
page
obiekt jestnull
.Jeśli warunek jest spełniony, Casper tworzy nowy
page
obiekt.Następnie
then()
sprawdza poprawnośćstep
parametru, aby sprawdzić, czy nie jest to funkcja.Jeśli parametr nie jest funkcją, wyświetla następujący błąd:
Następnie funkcja sprawdza, czy Casper działa.
Jeśli Casper nie jest uruchomiony,
then()
dołącza krok na koniec kolejki.W przeciwnym razie, jeśli Casper działa, wstawia podetap o poziom głębszy niż w poprzednim kroku.
Na koniec
then()
funkcja kończy się wyemitowaniemstep.added
zdarzenia i zwraca obiekt Casper.źródło