Perl WWW::Mechanize 作为子类;无法保持登录到抓取的网站

标签 perl subclass mechanize

我有一个使用 Perl WWW::Mechanize 的简单登录脚本。我正在编写登录 Moodle 的脚本.当我只是将登录步骤作为程序步骤执行时,它就起作用了。例如(假设“$site_url”、USERNAME 和 PASSWORD 已正确设置):

#THIS WORKS
$updater->get("http://".$site_url."/login/index.php");
$updater->form_id("login");
$updater->field('username', USERNAME);
$updater->field('password', PASSWORD);
$updater->click();
$updater->get("http://".$site_url."/");
print $updater->content();

当我尝试将这些步骤封装在 WWW:Mechanize 的子类中时,get() 和 content() 以及其他方法似乎有效,但登录站点却无效。我感觉它与可变范围有关,但我不知道如何解决它。

示例(失败):

my $updater = new AutoUpdater( $site_url, USERNAME, PASSWORD );
$updater->do_login();

{
package AutoUpdater;
use base qw( WWW::Mechanize );

sub new {
    my $class = shift;
    my $self = {
        site_url => shift,
        USERNAME => shift,
        PASSWORD => shift,
   };
    bless $self, $class;
    return $self;
}

sub do_login {
    my $self = shift;
    $self->get("http://".$site_url."/");
    $self->get("http://".$site_url."/login/index.php");
    $self->form_id("login");
    $self->field("username", $self->{USERNAME});
    $self->field("password", $self->{PASSWORD});
    $self->click();
    $self->get("http://".$site_url."/");
    print $self->content();
}
}

这失败了。 “失败”意味着它没有登录。不过它确实抓取了网页,我可以操作 HTML 数据。它只是不登录。耶! (是的,“yargh”是必要的)

谢谢!

最佳答案

修改后的版本:

use strict;
use warnings;

my $updater = AutoUpdater->new( $site_url, USERNAME, PASSWORD );
$updater->do_login();

{
package AutoUpdater;
use parent qw( WWW::Mechanize );

sub new {
  my $class = shift;

  my $self = $class->SUPER::new();

  $self->{AutoUpdater} = {
    site_url => shift,
    USERNAME => shift,
    PASSWORD => shift,
  };

  return $self;
}

sub do_login {
  my $self = shift;
  my $data = $self->{AutoUpdater};

  $self->get("http://$data->{site_url}/login/index.php");
  $self->form_id("login");
  $self->field("username", $data->{USERNAME});
  $self->field("password", $data->{PASSWORD});
  $self->click();
  $self->get("http://$data->{site_url}/");
  print $self->content();
}
} # end package AutoUpdater

一些注意事项:

您应该始终使用 strictwarnings帮助您发现错误。

不鼓励使用间接对象语法。使用 Class->new 而不是 new Class

base pragma 有一些不良影响,出于向后兼容性原因无法修复。 parent pragma 是为了取代它而开发的。

您的大问题是 Perl 不会自动初始化基类。如有必要,您必须显式调用 $class->SUPER::new

您的另一个大问题是了解如何处理对象实例数据。大多数 Perl 对象都是散列引用,您可以使用散列引用语法访问实例数据。当对一个我没有写的类进行子类化时,我喜欢使用第二个 hashref 来避免与父类发生冲突。请记住,您正在与基类共享对象。如果您的子类使用 site_url 字段,然后基类的后续版本开始使用 site_url 做其他事情,您的代码将突然中断,原因不明。通过在基对象 hashref 中仅使用一个键(以及基类不太可能开始使用的键),您可以最大限度地减少 future 损坏的可能性。

同时 Moose为 OO Perl 编程提供了一些不错的功能,如果您只是编写非 Moose 类的相当简单的子类,最好避免使用它。

关于Perl WWW::Mechanize 作为子类;无法保持登录到抓取的网站,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5861968/

相关文章:

Perl 等效于 (Postgresql BETWEEN 运算符?

java - 包含同一父类(super class)的不同对象的 ArrayList - 如何访问子类的方法

objective-c - PDFPage 子类上没有调用 init 吗?

python - 无法使用 BeautifulSoup 获取数据

python - Perl 的 HTML::Form::ForceValue 在 Python 中等效

python-requests - 尝试使用 urllib2 和请求在 python 中下载页面,但不断被重定向

algorithm - DAG : Self referencing HASH: searching the first level parent from any level child and then search leaves of that parent

perl - 将逻辑从 Template Toolkit 转移到 Catalyst

perl - 如何在 Perl 中向 Websocket 连接的客户端发送定期消息

ios - iOS 应用程序和子类化中的多个 UITableView Controller