WWW :: Mechanize - 如何POST而不影响页面堆栈和/或当前的HTML :: Form对象?

时间:2014-07-24 07:54:17

标签: perl www-mechanize

我正在使用WWW::Mechanize自动将“订单”放入供应商的门户网站(获得许可)。通过填写相关的表单字段和submit正常,这样做非常简单。

然而,该门户网站的构建考虑了一个支持JavaScript的客户端,因此采取了一些捷径;他们采取的最重要的捷径是,当您使用普通POSTS进行“向导”(一系列表单)时,他们需要您通过执行AJAX POST“解除分配”某些资源服务器端以进行“上一个向导步骤” 。在伪代码中:

GET page #1
fill the fields of page #1
POST (submit the form) --> redirects to page #2.
POST (ajax request to "/delete.do") 
fill the fields of page #2
POST (submit the form) --> redirects to page #3.
POST (ajax request to "/delete.do")
fill the fields of page #3.
...

执行这些ajax request to "/delete.do"请求的最简单方法是什么?

我试过......

Appoach(A)

如果我将新表单(在/delete.do中引用action)注入DOM并使用submit,那么mech对象将不再构建HTML::Form对象从上一个redirects to page #X步骤开始。

如果我从那时起只使用back(),是否会为服务器生成另一个GET? (或者它只是使用页面堆栈中的先前值?)

方法(B)

如果我只是使用从LWP :: UserAgent继承的post()方法将POST发送到/delete.do我收到安全错误 - 我猜它没有使用已设置的cookie jar通过WWW :: Mechanize。

是否有一些规范的方法来制作“带外”POST:

  • 使用/更新WWW :: Mechanize的cookie jar
  • 遵循重定向
  • 不会改变页面堆栈
  • 不会更改当前的HTML :: Form对象

UDPATE: 对于试图复制gangabass建议的解决方案的任何人,您实际上需要:

  

(1)子类WWW::Mechanize,覆盖update_html,以便a   可以根据需要将新内容注入HTML。

     

此内容通常由HTML::Form::parse()解析。该   override sub需要改变第一个非自身参数$html   在调用原始实现并返回结果之前。

package WWW::Mechanize::Debug;
use base 'WWW::Mechanize';

sub update_html {
  my ($self,$html) = @_;

  $html = $WWW::Mechanize::Debug::html_updater->($html)
    if defined($WWW::Mechanize::Debug::html_updater);

  return $self->SUPER::update_html($html);
}

1; 
     

(2)在主程序中,按照WWW::Mechanize::Debug使用   WWW::Mechanize

use WWW::Mechanize::Debug;
my $mech = WWW::Mechanize::Debug->new;
     

(3)注入需要submit()编辑的HTML表单。

{ 
  my $formHTML = qq| 
    <form action="/delete.do" method="POST" name="myform">
      <!-- some relevant hidden inputs go here in the real solution -->
    </form>
  |;

  local $WWW::Mechanize::html_updater = sub {
    my ($html) = @_;
    $html =~ s|</body>|$formHTML</body>|;
  };

  # Load the page containing the normal wizard step content.
  $mech->get($the_url); 

  # This should how have an extra form injected into it.                            
}
     

(4)在新范围clone()机械化对象中,填写表单并   提交吧!

{ 
   my $other = $mech->clone;
   my $myform = $separate->form_name('my_form');
   $myform->field('foo' => 'bar'); # fill in the relevant fields to be posted
   $myform->submit;
}
     

(5)继续使用原始的mechanize对象,就像该表单一样   提交从未发生过。

1 个答案:

答案 0 :(得分:2)

您需要clone您的Mech对象并从克隆版本进行POST。类似的东西:

{
    my $mech = $mech->clone();
    $mech->post(....);
}

但是,当然最好为此制作sub。