【问题标题】:How to submit a form using PhantomJS如何使用 PhantomJS 提交表单
【发布时间】:2012-03-04 00:34:02
【问题描述】:

我正在尝试使用 phantomJS(顺便说一句,多么棒的工具!)为我拥有登录凭据的页面提交表单,然后将目标页面的内容输出到标准输出。我可以使用幻像成功访问表单并设置其值,但我不太确定提交表单和输出后续页面内容的正确语法是什么。到目前为止我所拥有的是:

var page = new WebPage();
var url = phantom.args[0];

page.open(url, function (status) {

  if (status !== 'success') {
      console.log('Unable to access network');
  } else {

    console.log(page.evaluate(function () {

      var arr = document.getElementsByClassName("login-form");
      var i;

      for (i=0; i < arr.length; i++) {

        if (arr[i].getAttribute('method') == "POST") {
          arr[i].elements["email"].value="mylogin@somedomain.com";
          arr[i].elements["password"].value="mypassword";

          // This part doesn't seem to work. It returns the content
          // of the current page, not the content of the page after 
          // the submit has been executed. Am I correctly instrumenting
          // the submit in Phantom?
          arr[i].submit();
          return document.querySelectorAll('html')[0].outerHTML;
        }

      }

      return "failed :-(";

    }));
  }

  phantom.exit();
}

【问题讨论】:

    标签: javascript forms post phantomjs


    【解决方案1】:

    我想通了。基本上这是一个异步问题。您不能只提交并期望立即呈现后续页面。您必须等到触发下一页的 onLoad 事件。我的代码如下:

    var page = new WebPage(), testindex = 0, loadInProgress = false;
    
    page.onConsoleMessage = function(msg) {
      console.log(msg);
    };
    
    page.onLoadStarted = function() {
      loadInProgress = true;
      console.log("load started");
    };
    
    page.onLoadFinished = function() {
      loadInProgress = false;
      console.log("load finished");
    };
    
    var steps = [
      function() {
        //Load Login Page
        page.open("https://website.com/theformpage/");
      },
      function() {
        //Enter Credentials
        page.evaluate(function() {
    
          var arr = document.getElementsByClassName("login-form");
          var i;
    
          for (i=0; i < arr.length; i++) { 
            if (arr[i].getAttribute('method') == "POST") {
    
              arr[i].elements["email"].value="mylogin";
              arr[i].elements["password"].value="mypassword";
              return;
            }
          }
        });
      }, 
      function() {
        //Login
        page.evaluate(function() {
          var arr = document.getElementsByClassName("login-form");
          var i;
    
          for (i=0; i < arr.length; i++) {
            if (arr[i].getAttribute('method') == "POST") {
              arr[i].submit();
              return;
            }
          }
    
        });
      }, 
      function() {
        // Output content of page to stdout after form has been submitted
        page.evaluate(function() {
          console.log(document.querySelectorAll('html')[0].outerHTML);
        });
      }
    ];
    
    
    interval = setInterval(function() {
      if (!loadInProgress && typeof steps[testindex] == "function") {
        console.log("step " + (testindex + 1));
        steps[testindex]();
        testindex++;
      }
      if (typeof steps[testindex] != "function") {
        console.log("test complete!");
        phantom.exit();
      }
    }, 50);
    

    【讨论】:

    • 这是一个很棒的模板。这是我添加的一些内容:在setInterval 中使用var func = steps[testindex],然后使用console.log("step " + (testindex + 1) + ": " + funcName(func))。这允许您向正在执行的步骤添加描述。
    • 请参阅 here 以获取 funcName。此外,我发现在浏览一系列网页并尝试不同的技术时,使用page.render("output.png"); 呈现最后一页更容易。
    • 这篇文章真的很有帮助。一个问题。当您使用 POST 提交表单时,数据被发送到服务器,服务器返回响应。您处理此响应的代码在哪里,或者它是由 phantomjs 自动完成的?另外,表单提交后,服务器可以返回COOKIE,我的问题是:*当服务器返回响应时,phantom.cookies 对象中是否有这个cookie*
    • 使用 CasperJS 比 PhantomJS 更好,它可以发布到表单而无需复杂的编码
    【解决方案2】:

    此外,CasperJS 为 PhantomJS 中的导航提供了一个很好的高级界面,包括单击链接和填写表单。

    CasperJS

    更新为添加July 28, 2015 article comparing PhantomJS and CasperJS

    (感谢评论者M先生!)

    【讨论】:

    • Casper 对我不起作用,因为您只能使用名称填写表单输入。我需要使用 id。
    • @user984003 您应该可以将选择器设置为#someid 以根据 ID 进行填写。
    • CasperJS 是天赐之物!它使抓取 ASPX 页面变得轻而易举。谢谢!
    • @user984003 我不知道您是否使用的是旧版本,但当前版本有一个 fillSelectors() 可以使用任何选择器填充表单字段。
    • 任何使用 PhantomJS 的人都应该开始使用 CasperJS。这是描述原因的帖子:code-epicenter.com/why-is-casperjs-better-than-phantomjs
    【解决方案3】:

    发送原始 POST 请求有时会更方便。下面你可以看到来自 PhantomJS 的post.js original example

    // Example using HTTP POST operation
    
    var page = require('webpage').create(),
        server = 'http://posttestserver.com/post.php?dump',
        data = 'universe=expanding&answer=42';
    
    page.open(server, 'post', data, function (status) {
        if (status !== 'success') {
            console.log('Unable to post!');
        } else {
            console.log(page.content);
        }
        phantom.exit();
    });
    

    【讨论】:

    • 请注意,读者们,类似地执行GET 请求(通过执行page.open(server, 'get', data, ... 之类的操作)是行不通的。
    【解决方案4】:

    如上所述,CasperJS 是填写和发送表格的最佳工具。 如何使用fill() function 填写和提交表单的最简单示例:

    casper.start("http://example.com/login", function() {
    //searches and fills the form with id="loginForm"
      this.fill('form#loginForm', {
        'login':    'admin',
        'password':    '12345678'
       }, true);
      this.evaluate(function(){
        //trigger click event on submit button
        document.querySelector('input[type="submit"]').click();
      });
    });
    

    【讨论】:

      猜你喜欢
      • 2015-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 2013-12-25
      • 1970-01-01
      相关资源
      最近更新 更多