Как отправить форму с помощью PhantomJS

Я пытаюсь использовать 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="[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, данные отправляются на сервер, и сервер возвращает ответ. Где код, в котором вы обрабатываете этот ответ, или он автоматически выполняется фантомными js? Кроме того, после отправки формы сервер может вернуть COOKIE, и мой вопрос: * доступен ли этот файл 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 ('something) .value = 1st variable; document.getElementById ('что угодно'). значение = 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 для заполнения на основе идентификатора. - 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-лучше-чем-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