CasperJS를 사용하여 웹 사이트를 통해 일련의 클릭, 완성 된 양식, 데이터 구문 분석 등을 자동화하고 있습니다.
Casper는 then
명령문 형식의 사전 설정 단계 목록으로 구성되어있는 것 같습니다 (예 : http://casperjs.org/quickstart.html ).하지만 다음 명령문이 실제로 실행되도록 트리거하는 것은 명확하지 않습니다.
예를 들어 then
보류중인 모든 요청이 완료 될 때까지 기다리나요? injectJS
보류중인 요청으로 간주 됩니까 ? then
문이 중첩 된 경우-문 끝에 연결 되면 어떻게됩니까 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
});
CasperJS에서 흐름이 어떻게 작동하는지에 대한 기술적 설명을 찾고 있습니다. 내 특정 문제는 내 마지막 then
진술 (위)이 내 casper.open
진술 보다 먼저 실행되고 이유를 모르겠다는 것입니다.
답변
then()
기본적으로 스택에 새로운 탐색 단계를 추가합니다. 단계는 두 가지 다른 작업을 수행 할 수있는 자바 스크립트 함수입니다.
- 이전 단계 대기 (있는 경우) 실행 중
- 요청 된 URL 및 관련 페이지가로드되기를 기다리는 중
간단한 탐색 시나리오를 살펴 보겠습니다.
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)');
});
다음과 같이 스택 내에서 생성 된 모든 단계를 인쇄 할 수 있습니다.
require('utils').dump(casper.steps.map(function(step) {
return step.toString();
}));
그 결과 :
$ 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)'); }"
]
_step()
우리를 위해 URL을로드하기 위해 CasperJS에 의해 자동으로 추가 된 함수에 주목 하십시오. URL이로드되면 스택에서 사용할 수있는 다음 단계 (즉) step3()
가 호출됩니다.
탐색 단계를 정의한 경우 run()
순차적으로 하나씩 실행합니다.
casper.run();
각주 : 콜백 / 리스너 항목은 Promise 패턴 의 구현입니다 .
답변
then()
단순히 일련의 단계를 등록합니다.
run()
러너 함수, 콜백 및 리스너 제품군은 실제로 각 단계를 실행하는 작업을 수행합니다.
단계가 완료 될 때마다, CasperJS 3 개 플래그에 대해 확인합니다 : pendingWait
, loadInProgress
,와 navigationRequested
. 이러한 플래그 중 하나라도 참이면 아무것도하지 않고 나중에 유휴 상태로 유지합니다 ( setInterval
스타일). 해당 플래그 중 어느 것도 참이 아니면 다음 단계가 실행됩니다.
CasperJS 1.0.0-RC4에서 결함이 존재합니다. 특정 시간 기반 상황에서 CasperJS가 loadInProgress
또는 navigationRequested
플래그 중 하나를 발생시키기 전에 “다음 단계를 시도”메소드가 트리거됩니다 . 해결책은 플래그가 발생할 것으로 예상되는 단계를 떠나기 전에 플래그 중 하나를 발생시키는 것입니다 (예 : a를 요청하기 전이나 후에 플래그를 올림 casper.click()
).
(참고 : 이것은 적절한 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()
}
코드 한 줄에 해당 솔루션을 마무리하기 위해, 나는 도입 blockStep()
이 github의의에 끌어 오기 요청 확장 click()
및 clickLabel()
사용할 때 우리가 예상 된 동작을 얻을 도움을 보증하는 수단으로 then()
. 자세한 정보, 사용 패턴 및 최소 테스트 파일에 대한 요청을 확인하십시오.
답변
CasperJS 문서 에 따르면 :
then()
서명: then(Function then)
이 방법은 간단한 기능을 제공하여 스택에 새 탐색 단계를 추가하는 표준 방법입니다.
casper.start('http://google.fr/');
casper.then(function() {
this.echo('I\'m in your google.');
});
casper.then(function() {
this.echo('Now, let me write something');
});
casper.then(function() {
this.echo('Oh well.');
});
casper.run();
필요한만큼 단계를 추가 할 수 있습니다. 현재
Casper
인스턴스this
는 단계 함수 내 에서 키워드를 자동으로 바인딩합니다 .정의한 모든 단계를 실행하려면
run()
메서드를 호출하면됩니다 .참고 : 당신은해야한다
start()
순서 캐스퍼 인스턴스가 사용하는then()
방법을.경고 :에 추가 된 단계 함수
then()
는 두 가지 다른 경우에 처리됩니다.
- 이전 단계 기능이 실행되면
- 이전 메인 HTTP 요청이 실행되고 페이지가 로드 되었을 때 ;
로드 된 페이지의 단일 정의는 없습니다 . DOMReady 이벤트가 트리거되었을 때입니까? “모든 요청이 완료 중”입니까? “모든 응용 프로그램 논리가 수행되고”있습니까? 아니면 “렌더링되는 모든 요소”? 대답은 항상 상황에 따라 다릅니다. 따라서
waitFor()
실제로 기대하는 것을 명시 적으로 제어하기 위해 항상 가족 방법을 사용하도록 권장됩니다 .일반적인 트릭은 다음을 사용하는 것입니다
waitForSelector()
.
casper.start('http://my.website.com/');
casper.waitForSelector('#plop', function() {
this.echo('I\'m sure #plop is available in the DOM');
});
casper.run();
이면의 소스 코드Casper.prototype.then
는 다음과 같습니다.
/**
* Schedules the next step in the navigation process.
*
* @param function step A function to be called as a step
* @return Casper
*/
Casper.prototype.then = function then(step) {
"use strict";
this.checkStarted();
if (!utils.isFunction(step)) {
throw new CasperError("You can only define a step as a function");
}
// check if casper is running
if (this.checker === null) {
// append step to the end of the queue
step.level = 0;
this.steps.push(step);
} else {
// insert substep a level deeper
try {
step.level = this.steps[this.step - 1].level + 1;
} catch (e) {
step.level = 0;
}
var insertIndex = this.step;
while (this.steps[insertIndex] && step.level === this.steps[insertIndex].level) {
insertIndex++;
}
this.steps.splice(insertIndex, 0, step);
}
this.emit('step.added', step);
return this;
};
설명:
즉, then()
탐색 프로세스의 다음 단계를 예약합니다.
를 then()
호출하면 단계로 호출 될 매개 변수로 함수가 전달됩니다.
인스턴스가 시작되었는지 확인하고 시작되지 않은 경우 다음 오류를 표시합니다.
CasperError: Casper is not started, can't execute `then()`.
다음으로 page
객체가 null
.
조건이 참이면 Casper는 새 page
개체를 만듭니다 .
그 후 매개 변수의 then()
유효성 step
을 검사하여 함수가 아닌지 확인합니다.
매개 변수가 함수가 아닌 경우 다음 오류가 표시됩니다.
CasperError: You can only define a step as a function
그런 다음이 함수는 Casper가 실행 중인지 확인합니다.
Casper가 실행 중이 아니면 then()
대기열 끝에 단계를 추가합니다.
그렇지 않고 Casper가 실행 중이면 이전 단계보다 한 단계 더 깊은 하위 단계를 삽입합니다.
마지막으로 then()
함수는 step.added
이벤트를 생성하여 종료하고 Casper 객체를 반환합니다.