3

我正在玩 Win32::IE::Mechanize。我正在尝试一个脚本来自动访问我的六个基于 Web 的电子邮件帐户。该脚本基本上可以工作,但 perl 会抛出一种神秘的“无法通过包“sssself”定位对象方法“警告”(也许你忘记加载“sssself”)错误。尽管出现错误,脚本仍然可以完成工作.但我想摆脱它并了解它为什么会发生。以下是脚本。请在我可以改进代码的地方发表评论。一如既往地感谢。

use strict;
use Win32::IE::Mechanize;


my @accounts = (
'http://mail.21cn.com',
'frmmail1',
    {
        'Username' => 'myusername',
        'passwd' => 'mypassword',
        },
'http://mail.126.com',
'form',
    {
        'user' => 'myusername',
        'password' => 'mypassword',
        },
......
......
......
    );

sub arg{
shift (@accounts);
}

while(@accounts){
my $mech = Win32::IE::Mechanize->new(visible=>1);
my $url = arg;
my $form = arg;
my $account = arg;

$mech->get($url);
$mech->form_name($form);
eval {$mech->set_fields(%$account);}; 
warn $@ if $@;
$mech->click();
}

我知道线路有问题

$mech->set_fields(%$account);

但是我该如何纠正呢?还是我应该删除

warn $@ if $@;

假装没事?

欢迎任何意见:)

更新

谢谢@daotoad 清理我的丑陋代码 :) 我认为嵌套结构更易于维护且美观。

并感谢@Eric,为我指出了相关模块的更好版本:)

好吧,事情是当 Win32::IE:Mechanize 0.009 给出以下神秘的错误消息时

无法在 C:/Perl/site/lib/Win32/IE/Mechanize.pm 第 971 行通过包“sssself”找到对象方法“warn”(也许您忘记加载“sssself”?)。

0.009_17 Dev Release 给了我一些非常有意义的信息:

在 E:\mailme.pl 第 33 行没有名为“用户名”的输入控件

考虑到这个错误信息,我检查了登录页面的源文件,结果发现字段 id 应该是“用户名”,而不是“用户名”。

所以我解决了我的问题:) 谢谢你们!

4

2 回答 2

4

Win32::IE::Mechanize 版本 0.009 中似乎存在错误。有一个开发者版本 0.009_17可能会更好。我还没有测试过,但至少'sssself'是固定的。如果 IE 不是必需的,那么也有WWW::Mechanize::FirefoxWWW::Mechanize如果不需要浏览器。

于 2010-02-27T06:32:58.120 回答
2

我没有时间给你真正的好答案 ATM,但这里是代码的清理。看看评论。如果您对我做了什么或为什么有任何疑问,请在下面发表评论,我会更新问题。

#!/usr/bin/perl
use strict;
use warnings;  # Use warnings - see perldoc perllexwarn

use Try::Tiny;  # Don't try to handle your own exceptions.  Try::Tiny does it better.

use Win32::IE::Mechanize;

# Use a nested structure so you don't have to keep popping stuff off a global array.   
my @accounts = (

    {   url       => 'http://mail.21cn.com',
        form_id => 'frmmail1',
        fields => {
            Username   => 'myusername',
            passwd     => 'mypassword',
        }
    },
    {   url => 'http://mail.126.com',
        form_id => 'form',
        fields => {
            user => 'myusername',
            password => 'mypassword',
        },
    },
);

# No messing about with @accounts means we can use a for loop.
for my $account (@accounts) {

    # Its not necessary to unpack these into scalars.
    # It makes sense if you are going to transform the values or use them many times.
    my $url    = $account->{url};
    my $form   = $account->{form_id};
    my $fields = $account->{fields};

    my $mech = Win32::IE::Mechanize->new(visible=>1);

    $mech->get($url);
    $mech->form_name($form);

    # Exception handling redone with Try::Tiny    
    $mech->click() if try { 
        $mech->set_fields(%$fields);
        1;
    }
    catch {
        warn "Form failed - $_\n";
    };
}
于 2010-02-27T03:14:51.883 回答