Как да изпратите формуляр с помощта на PhantomJS

Опитвам се да използвам phantomJS (какъв страхотен инструмент между другото!), за да изпратя формуляр за страница, за която имам идентификационни данни за вход, и след това да изведа съдържанието на целевата страница в stdout. Мога да осъществя достъп до формуляра и да задам стойностите му успешно с помощта на фантом, но не съм съвсем сигурен какъв е правилният синтаксис за изпращане на формуляра и извеждане на съдържанието на следващата страница. Това, което имам досега е:

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="[email protected]";
          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();
}

person Vijay Boyapati    schedule 12.02.2012    source източник


Отговори (4)


Разбрах го. По принцип това е асинхронен проблем. Не можете просто да изпратите и да очаквате да изобразите следващата страница веднага. Трябва да изчакате, докато се задейства събитието 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);
person Vijay Boyapati    schedule 13.02.2012
comment
това е страхотен шаблон. Ето няколко неща, които добавих: вътре в setInterval използвайте var func = steps[testindex], след това console.log("step " + (testindex + 1) + ": " + funcName(func)). Това ви позволява да добавите описание към изпълняваните стъпки. - person Jonno; 19.05.2014
comment
вижте тук за funcName. Освен това установих, че е по-лесно, когато преминавам през поредица от уеб страници и опитвам различни техники, да изобразя последната страница с помощта на page.render("output.png");. - person Jonno; 19.05.2014
comment
Това е наистина полезна публикация. Един въпрос обаче. Когато изпратите формуляр чрез POST, данните се изпращат до сървъра и сървърът връща отговор. Къде е кодът, където обработвате този отговор или той се извършва автоматично от phantomjs? Освен това след подаване на формуляр сървърът може да върне COOKIE и въпросът ми е: *налична ли е тази бисквитка в phantom.cookies обект, когато сървърът върне отговор*? - person MrD; 15.07.2015
comment
използвайте CasperJS, той е по-добър от PhantomJS, има възможност да публикува във формуляри без сложно кодиране - person waza123; 02.03.2016
comment
Можете ли да проверите и това stackoverflow.com/questions/44624964 /phantom-js-on-web-project - person Manik; 19.06.2017
comment
@Vijay Boyapati Знам, че това е старо и вашето решение работи. Във вашето решение вашето потребителско име и парола са твърдо кодирани. Какво ще стане, ако чета csv списък с променливи, които искам да предам в page.evaluate(function()), така че да изглежда като нещо подобно: document.getElementById('whatever).value = 1st variable; document.getElementById('каквото').value = 2-ра променлива; ? - person Proximus Seraphim Dimitri Davi; 19.02.2020

Освен това CasperJS предоставя приятен интерфейс на високо ниво за навигация във PhantomJS, включително щракване върху връзки и попълване на формуляри.

CasperJS

Актуализиран, за да добави статия от 28 юли 2015 г., сравняваща PhantomJS и CasperJS .

(Благодаря на коментатора г-н М!)

person arboc7    schedule 18.03.2012
comment
Casper не работи за мен, защото можете да попълните въвеждане на формуляр само с име. Трябваше да използвам id. - person user984003; 01.04.2013
comment
@user984003 Трябва да можете да зададете селектора си на #someid, за да попълните въз основа на ID. - person arboc7; 02.04.2013
comment
CasperJS е божи дар! Това прави изтриването на ASPX страници лесно. Благодаря ти! - person Tobia; 28.05.2014
comment
@user984003 Не знам дали сте използвали по-стара версия, но текущата има fillSelectors() за попълване на полета на формуляр с помощта на произволен селектор. - person Tobia; 28.05.2014
comment
Всеки, който използва PhantomJS, трябва да започне да използва CasperJS. Ето публикация, описваща защо: code-epicenter.com/why-is -casperjs-better-than-phantomjs - person MrD; 28.07.2015

Изпращането на необработени POST заявки понякога може да бъде по-удобно. По-долу можете да видите оригинален пример за post.js от 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();
});
person Jakub M.    schedule 04.02.2013
comment
Имайте предвид, читатели, че изпълнението на GET заявки по подобен начин (като направите нещо като page.open(server, 'get', data, ...) няма да работи. - person zbr; 06.10.2014

Както беше споменато по-горе CasperJS е най-добрият инструмент за попълване и изпращане на формуляри. Най-простият възможен пример за това как да попълните и изпратите формуляр с помощта на функция 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();
  });
});
person DominikStyp    schedule 05.03.2016