我使用 PhantomJS 和 CasperJS 来自动执行某些任务。在其中一项任务中,我需要在实际处理任务之前手动提供验证码字符串。对于这个问题,我能想到的是捕获网页的屏幕截图,然后手动检查捕获的图像并将验证码字符串保存到文本文件中。之后,我可以使用 CasperJS 中的文件系统模块来读取该值并继续执行该过程。我想知道做这种任务的最佳方法是什么。
答案 0 :(得分:12)
由于CasperJS与PhantomJS相比具有结构化的方式/控制流程,因此这项任务并不容易。
假设有一个辅助程序(类型1)处理显示CAPTCHA,接收输入并使用CAPTCHA输入写入文本文件。 CasperJS可以处理的就是将CAPTCHA屏幕截图写入磁盘并等待带有“已解析”文本的文件。
var fs = require("fs"),
captchaFile = "cfile.png",
parsedFile = "pfile.txt";
casper.waitForCaptcha = function(captchaFile, parsedFile){
casper.then(function(){
this.captureSelector(captchaFile, "someSelectorOfTheCaptcha");
});
casper.waitFor(function check(){
return fs.exists(parsedFile);
}, function then(){
// do something on time
// check if correct...
if (!correct) {
fs.remove(captchaFile);
fs.remove(parsedFile);
this.waitForCaptcha(captchaFile, parsedFile);
// Problem: the secondary process needs to sense that a new CAPTCHA is presented
}
}, function onTimeout(){
// do something when failed
}, 60000); // 1min should suffice as a timeout
return this;
};
casper.start(url).waitForCaptcha(captchaFile, parsedFile).run();
此代码假定您要在CAPTCHA错误时重试,但如果没有解码文件故意传递分钟则不会。这是一个拉取过程,通过轮询文件是否已经存在。
也可以使用推送过程,其中辅助程序(类型2)使用PhantomJS webserver module向CasperJS进程发送请求。因为将存在两个并发控制流,所以CasperJS部分需要等待很长时间,但是一旦收到带有解码字的请求,就可以用unwait
打破等待。
var server = require('webserver').create(),
fs = require("fs"),
captchaFile = "cfile.png";
function neverendingWait(){
this.wait(5000, neverendingWait);
}
casper.checkCaptcha = function(captchaFile, phantomPort, secondaryPort){
// here the CAPTCHA is saved to disk but it can also be set directly if captured through casper.captureBase64
this.captureSelector(captchaFile, "someSelectorOfTheCaptcha");
// send request to the secondary program from the page context
this.evaluate(function(file){
__utils__.sendAJAX("http://localhost:"+secondaryPort+"/", "POST", {file: file}, true);
}, captchaFile);
// start the server to receive solved CAPTCHAs
server.listen(phantomPort, {
'keepAlive': true
}, function (request, response) {
console.log('Request received at ' + new Date());
if (request.post) { // is there a response?
this.then(function(){
// check if it is correct by reading request.post ...
if (!correct){
response.statusCode = 404;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
};
response.close();
server.close();
this.checkCaptcha(captchaFile, phantomPort, secondaryPort);
} else {
response.statusCode = 200;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
};
response.close();
server.close();
this.unwait(); // abort the neverendingWait
}
});
} else {
response.statusCode = 404;
response.headers = {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
};
response.close();
server.close();
this.checkCaptcha(captchaFile, phantomPort, secondaryPort);
}
});
return this;
};
casper.start(url).then(function(){
this.checkCaptcha(captchaFile, 8080, 8081);
}).then(neverendingWait).then(function(){
// Do something here when the captcha is successful
}).run();