Cách gửi biểu mẫu bằng PhantomJS


161

Tôi đang cố gắng sử dụng ph PhantomJS (thật là một công cụ tuyệt vời btw!) Để gửi biểu mẫu cho một trang mà tôi có thông tin đăng nhập, sau đó xuất nội dung của trang đích ra thiết bị xuất chuẩn. Tôi có thể truy cập biểu mẫu và đặt thành công các giá trị của nó bằng cách sử dụng ảo, nhưng tôi không chắc chắn cú pháp đúng là gì để gửi biểu mẫu và xuất nội dung của trang tiếp theo. Những gì tôi có cho đến nay là:

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();
}

Câu trả lời:


227

Tôi đã hiểu rồi. Về cơ bản đó là một vấn đề không đồng bộ. Bạn không thể gửi và mong đợi kết xuất trang tiếp theo ngay lập tức. Bạn phải đợi cho đến khi sự kiện onLoad cho trang tiếp theo được kích hoạt. Mã của tôi dưới đây:

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);

3
đây là một mẫu tuyệt vời Dưới đây là một vài điều tôi đã thêm: setIntervalsử dụng bên trong var func = steps[testindex], sau đó console.log("step " + (testindex + 1) + ": " + funcName(func)). Điều này cho phép bạn thêm mô tả cho các bước đang được thực hiện.
Jonno

xem ở đây cho funcName. Ngoài ra tôi thấy dễ dàng hơn khi đi qua một loạt các trang web và thử các kỹ thuật khác nhau, để hiển thị trang cuối cùng bằng cách sử dụng page.render("output.png");.
Jonno

2
Đây thực sự là bài viết hữu ích. Một câu hỏi mặc dù. Khi bạn gửi biểu mẫu bằng POST, dữ liệu sẽ được gửi đến máy chủ và máy chủ trả về phản hồi. Mã nơi bạn xử lý phản hồi này ở đâu hoặc nó được tự động thực hiện bởi ph Phantomjs? Ngoài ra, sau khi gửi biểu mẫu, một máy chủ có thể trả về COOKIEvà câu hỏi của tôi là: * cookie này có sẵn trong phantom.cookiesđối tượng khi máy chủ trả lời phản hồi * không?
MrD

sử dụng CasperJS tốt hơn PhantomJS, nó có khả năng đăng lên các biểu mẫu mà không cần mã hóa phức tạp
waza123

Bạn có thể vui lòng kiểm tra quá stackoverflow.com/questions/44624964/ph
Phantom

62

Ngoài ra, CasperJS cung cấp một giao diện cấp cao đẹp để điều hướng trong PhantomJS, bao gồm nhấp vào liên kết và điền vào biểu mẫu.

CasperJS

Cập nhật để thêm bài viết ngày 28 tháng 7 năm 2015 so sánh PhantomJS và CasperJS .

(Cám ơn bình luận viên M!)


1
Casper không hoạt động với tôi vì bạn chỉ có thể điền vào một mẫu nhập bằng tên. Tôi cần sử dụng id.
user984003

4
@ user984003 Bạn sẽ có thể đặt bộ chọn của mình #someidđể điền vào dựa trên ID.
arboc7

2
CasperJS là một ơn trời! Nó làm cho việc quét các trang ASPX trở nên dễ dàng. Cảm ơn bạn!
Tobia

@ user984003 Tôi không biết nếu bạn đang sử dụng phiên bản cũ hơn, nhưng phiên bản hiện tại có fillSelector () để điền vào các trường mẫu bằng bất kỳ bộ chọn nào.
Tobia

3
Bất cứ ai đang sử dụng PhantomJS nên bắt đầu sử dụng CasperJS. Đây là bài viết mô tả lý do tại sao: code-epicenter.com/why-is-casperjs-better-than-ph Phantomjs
MrD

19

Gửi yêu cầu POST thô đôi khi có thể thuận tiện hơn. Dưới đây bạn có thể xem ví dụ ban đầu của post.js từ PhantomJS

// 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();
});

6
Xin lưu ý, các độc giả, thực hiện GETcác yêu cầu tương tự (bằng cách làm một cái gì đó như page.open(server, 'get', data, ...) sẽ không hoạt động.
zbr

7

Như đã đề cập ở trên, CasperJS là công cụ tốt nhất để điền và gửi biểu mẫu. Ví dụ đơn giản nhất có thể về cách điền và gửi biểu mẫu bằng hàm fill () :

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();
  });
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.