我有一个使用 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
一些注意事项:
您应该始终使用 strict和 warnings帮助您发现错误。
不鼓励使用间接对象语法。使用 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/