如何使用Casperjs登录后下载csv文件

时间:2015-05-11 06:34:31

标签: javascript csv casperjs

我想通过使用Caperjs来下载csv文件。 这就是我写的:

var login_id = "my_user_id";
var login_password = "my_password";

var casper = require('casper').create();

casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36 ');

casper.start("http://eoddata.com/symbols.aspx",function(){
    this.evaluate(function(id,password) {
        document.getElementById('tl00_cph1_ls1_txtEmail').value = id;
        document.getElementById('ctl00_cph1_ls1_txtPassword').value = password;
        document.getElementById('ctl00_cph1_ls1_btnLogin').submit();

    }, login_id, login_password);
});

casper.then(function(){
    this.wait(3000, function() {
        this.echo("Wating...");
    });
});

casper.then(function(){
    this.download("http://eoddata.com/Data/symbollist.aspx?e=NYSE","nyse.csv");
});

casper.run();

我得到nyse.csv,但该文件是用于注册网站的HTML文件。

似乎登录过程失败。如何正确登录并保存csv文件?

2015年5月13日

在@ Darren的帮助下,我写道:

casper.start("http://eoddata.com/symbols.aspx");
casper.waitForSelector("form input[name = ctl00$cph1$ls1$txtEmail ]", function() {
  this.fillSelectors('form', {
    'input[name = ctl00$cph1$ls1$txtEmail ]' : login_id,
    'input[name = ctl00$cph1$ls1$txtPassword ]' : login_password,
    }, true);
});

此代码最终会出现错误Wait timeout of 5000ms expired, exiting.。 据我所知,错误意味着CSS选择器无法找到该元素。我怎样才能找到解决这个问题的方法?

2015/05/18更新

我是这样写的:

casper.waitForSelector("form input[name = ctl00$cph1$ls1$txtEmail]", function() {
    this.fillSelectors('form', {
        'input[name = ctl00$cph1$ls1$txtEmail]' : login_id,
        'input[name = ctl00$cph1$ls1$txtPassword]' : login_password,
    }, true);
}, function() {
    fs.write("timeout.html", this.getHTML(), "w");
    casper.capture("timeout.png");
});

我通过Chrome开发者工具和Firebugs检查了timeout.html,并且我多次确认存在input元素。

<input name="ctl00$cph1$ls1$txtEmail" id="ctl00_cph1_ls1_txtEmail" style="width:140px;" type="text">

如何解决此问题?我已经花了几个小时来解决这个问题。

更新2015/05/19

感谢Darren,Urarist和Artjom我可以删除超时错误,但还有另一个错误。

下载的CSV文件仍然是注册html文件,所以我重写了这样的代码以找出错误原因:

casper.waitForSelector("form input[name ='ctl00$cph1$ls1$txtEmail']", function() {
    this.fillSelectors('form', {
        "input[name ='ctl00$cph1$ls1$txtEmail']" : login_id,
        "input[name ='ctl00$cph1$ls1$txtPassword']" : login_password,
    }, true);
});/*, function() {
    fs.write("timeout.html", this.getHTML(), "w");
    casper.capture("timeout.png");
});*/

casper.then(function(){
    fs.write("logined.html", this.getHTML(), "w");
});

logined.html用户中,电子邮件已正确填写,但未填写密码。有没有人猜测这个原因?

2 个答案:

答案 0 :(得分:1)

乍一看,您的脚本看起来很合理。但是有几种方法可以使它更简单,这也应该使它更健壮。

首先,而不是evaluate()行,

this.fillSelectors('form', {
  'input[name = id ]' : login_id,
  'input[name = pw ]' : login_password,
  }, true);

true参数表示提交。 (我猜到了表单名称,但我相信你可以继续使用CSS ID。)

但是,更好的是在你确定它存在之前不填写表格:

casper.waitForSelector("form input[name = id ]", function() {
  this.fillSelectors('form', {
    'input[name = id ]' : login_id,
    'input[name = pw ]' : login_password,
    }, true);
});

如果登录表单是由JavaScript动态放置在那里(甚至可能来自Ajax调用),这将非常重要,因此一旦加载页面就不会在页面上存在。

另一个更改不是使用casper.wait(),而是在尝试下载之前使用其中一个casper.waitForXXX()来确保csv文件链接在那里。如果远程服务器响应时间超过3.1秒,则等待3秒将出错,如果远程服务器只需1秒钟响应,则会浪费时间。

更新:当您在waitFor行上超时时,它会告诉您问题的根源是您正在使用不存在的选择器。我发现,这是编写Casper脚本时最大的时间消费者。 (我最近设想了一个工具,可以自动尝试找到一个接近错过,但无法让任何其他人感兴趣,这对一个人来说有点太大了。)所以你的故障排除起点将是:

  • 向超时waitFor()命令添加错误处理程序并截取屏幕截图(casper.capture())。
  • Dump the HTML。如果你知道父div的ID,你可以给它,缩小你需要查找的数量。
  • 使用FireBug(或您选择的工具)打开页面,然后四处寻找可以找到的内容。 (请记住,您可以在控制台中键入jQuery命令或document.querySelector()命令,这是交互式查找正确选择器的好方法。)
  • 尝试使用SlimerJS,而不是PhantomJS(特别是如果仍然使用PhantomJS 1.x)。可能是该网站使用的某些功能仅在较新的浏览器中受支持。

答案 1 :(得分:1)

诀窍是成功登录。有多种登录方式。我已经尝试了一些,唯一适用于此页面的是使用回车键触发表单提交。这是通过使用PhantomJS page.sendEvent()函数完成的。可以使用casper.sendKeys()填写字段。

var casper = require('casper').create();

casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36 ');

casper.start("http://eoddata.com/symbols.aspx",function(){
    this.sendKeys("#ctl00_cph1_ls1_txtEmail", login_id);
    this.sendKeys("#ctl00_cph1_ls1_txtPassword", login_password, {keepFocus: true});
    this.page.sendEvent("keypress", this.page.event.key.Enter);
});

casper.waitForUrl(/myaccount/, function(){
    this.download("http://eoddata.com/Data/symbollist.aspx?e=NYSE", "nyse.csv");
});

casper.run();

似乎有必要等待该特定页面。 CasperJS没有注意到请求了新页面,并且由于某种原因未使用then() functionality

我尝试的其他方式是:

  • 使用casper.fillSelectors()
  • 填写并提交表单
  • 使用casper.evaluate()填充DOM,然后点击带有casper.click()
  • 的登录按钮进行提交
  • 混合以上所有内容。
相关问题